@runhalo/engine 0.3.1 → 0.5.0
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/dist/ast-engine.d.ts +60 -0
- package/dist/ast-engine.js +653 -0
- package/dist/ast-engine.js.map +1 -0
- package/dist/context-analyzer.d.ts +209 -0
- package/dist/context-analyzer.js +401 -0
- package/dist/context-analyzer.js.map +1 -0
- package/dist/data-flow-tracer.d.ts +106 -0
- package/dist/data-flow-tracer.js +506 -0
- package/dist/data-flow-tracer.js.map +1 -0
- package/dist/frameworks/django.d.ts +11 -0
- package/dist/frameworks/django.js +57 -0
- package/dist/frameworks/django.js.map +1 -0
- package/dist/frameworks/index.d.ts +59 -0
- package/dist/frameworks/index.js +93 -0
- package/dist/frameworks/index.js.map +1 -0
- package/dist/frameworks/nextjs.d.ts +11 -0
- package/dist/frameworks/nextjs.js +59 -0
- package/dist/frameworks/nextjs.js.map +1 -0
- package/dist/frameworks/rails.d.ts +11 -0
- package/dist/frameworks/rails.js +58 -0
- package/dist/frameworks/rails.js.map +1 -0
- package/dist/frameworks/types.d.ts +29 -0
- package/dist/frameworks/types.js +11 -0
- package/dist/frameworks/types.js.map +1 -0
- package/dist/index.d.ts +74 -0
- package/dist/index.js +235 -28
- package/dist/index.js.map +1 -1
- package/dist/scope-analyzer.d.ts +91 -0
- package/dist/scope-analyzer.js +300 -0
- package/dist/scope-analyzer.js.map +1 -0
- package/package.json +6 -2
- package/rules/rules.json +2632 -0
- package/rules/validation-report.json +58 -0
package/rules/rules.json
ADDED
|
@@ -0,0 +1,2632 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0.0",
|
|
3
|
+
"generated_at": "2026-03-02T00:00:00Z",
|
|
4
|
+
"packs": {
|
|
5
|
+
"coppa": {
|
|
6
|
+
"id": "coppa",
|
|
7
|
+
"name": "COPPA 2.0 Core",
|
|
8
|
+
"description": "25 rules for COPPA & COPPA 2.0 compliance. Effective April 22, 2026.",
|
|
9
|
+
"jurisdiction": "US-Federal",
|
|
10
|
+
"jurisdiction_level": "federal",
|
|
11
|
+
"is_free": true,
|
|
12
|
+
"effective_date": "2026-04-22",
|
|
13
|
+
"source_url": "https://www.ecfr.gov/current/title-16/chapter-I/subchapter-C/part-312"
|
|
14
|
+
},
|
|
15
|
+
"ethical": {
|
|
16
|
+
"id": "ethical",
|
|
17
|
+
"name": "Ethical Design",
|
|
18
|
+
"description": "5 rules detecting dark patterns that exploit children's psychology.",
|
|
19
|
+
"jurisdiction": "international",
|
|
20
|
+
"jurisdiction_level": "advisory",
|
|
21
|
+
"is_free": true,
|
|
22
|
+
"effective_date": null,
|
|
23
|
+
"source_url": "https://runhalo.dev/ethical-design"
|
|
24
|
+
},
|
|
25
|
+
"ai-audit": {
|
|
26
|
+
"id": "ai-audit",
|
|
27
|
+
"name": "AI-Generated Code Audit",
|
|
28
|
+
"description": "6 rules catching COPPA risks commonly introduced by AI coding assistants.",
|
|
29
|
+
"jurisdiction": "international",
|
|
30
|
+
"jurisdiction_level": "advisory",
|
|
31
|
+
"is_free": true,
|
|
32
|
+
"effective_date": null,
|
|
33
|
+
"source_url": "https://runhalo.dev/ai-audit"
|
|
34
|
+
},
|
|
35
|
+
"au-sbd": {
|
|
36
|
+
"id": "au-sbd",
|
|
37
|
+
"name": "AU Safety by Design",
|
|
38
|
+
"description": "6 rules based on Australia's eSafety Commissioner Safety by Design framework.",
|
|
39
|
+
"jurisdiction": "AU-Federal",
|
|
40
|
+
"jurisdiction_level": "federal",
|
|
41
|
+
"is_free": false,
|
|
42
|
+
"effective_date": "2021-01-23",
|
|
43
|
+
"source_url": "https://www.esafety.gov.au/industry/safety-by-design"
|
|
44
|
+
},
|
|
45
|
+
"ut-sb142": {
|
|
46
|
+
"id": "ut-sb142",
|
|
47
|
+
"name": "Utah SB 142 (App Store Accountability)",
|
|
48
|
+
"description": "5 rules for Utah SB 142 compliance — age assurance, parental consent, minor account defaults, DM restrictions, and supervisory tools.",
|
|
49
|
+
"jurisdiction": "US-UT",
|
|
50
|
+
"jurisdiction_level": "state",
|
|
51
|
+
"is_free": true,
|
|
52
|
+
"effective_date": "2026-05-06",
|
|
53
|
+
"source_url": "https://le.utah.gov/~2025/bills/static/SB0142.html"
|
|
54
|
+
},
|
|
55
|
+
"uk-aadc": {
|
|
56
|
+
"id": "uk-aadc",
|
|
57
|
+
"name": "UK Age Appropriate Design Code",
|
|
58
|
+
"description": "15 rules for the UK ICO Children's Code (AADC) — the 15 standards for age-appropriate online services.",
|
|
59
|
+
"jurisdiction": "UK",
|
|
60
|
+
"jurisdiction_level": "national",
|
|
61
|
+
"is_free": false,
|
|
62
|
+
"effective_date": "2021-09-02",
|
|
63
|
+
"source_url": "https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/childrens-information/childrens-code-guidance-and-resources/age-appropriate-design-a-code-of-practice-for-online-services/"
|
|
64
|
+
},
|
|
65
|
+
"eu-dsa": {
|
|
66
|
+
"id": "eu-dsa",
|
|
67
|
+
"name": "EU DSA Article 28 (Minor Protection)",
|
|
68
|
+
"description": "10 rules for EU Digital Services Act Article 28 — online protection of minors on platforms.",
|
|
69
|
+
"jurisdiction": "EU",
|
|
70
|
+
"jurisdiction_level": "supranational",
|
|
71
|
+
"is_free": false,
|
|
72
|
+
"effective_date": "2024-02-17",
|
|
73
|
+
"source_url": "https://www.eu-digital-services-act.com/Digital_Services_Act_Article_28.html"
|
|
74
|
+
},
|
|
75
|
+
"au-osa": {
|
|
76
|
+
"id": "au-osa",
|
|
77
|
+
"name": "AU Online Safety Act",
|
|
78
|
+
"description": "12 rules for Australia's Online Safety Act 2021 (as amended 2024) — age verification, content moderation, under-16 social media ban, and eSafety Commissioner compliance.",
|
|
79
|
+
"jurisdiction": "AU-Federal",
|
|
80
|
+
"jurisdiction_level": "federal",
|
|
81
|
+
"is_free": false,
|
|
82
|
+
"effective_date": "2025-01-01",
|
|
83
|
+
"source_url": "https://www.esafety.gov.au/whats-on/online-safety-act"
|
|
84
|
+
},
|
|
85
|
+
"caadca": {
|
|
86
|
+
"id": "caadca",
|
|
87
|
+
"name": "California AADCA",
|
|
88
|
+
"description": "15 rules for the California Age-Appropriate Design Code Act (AB 2273) — default privacy, age estimation, profiling restrictions, dark pattern prohibitions, and data minimization for child users.",
|
|
89
|
+
"jurisdiction": "US-CA",
|
|
90
|
+
"jurisdiction_level": "state",
|
|
91
|
+
"is_free": false,
|
|
92
|
+
"effective_date": "2024-07-01",
|
|
93
|
+
"source_url": "https://leginfo.legislature.ca.gov/faces/billNavClient.xhtml?bill_id=202120220AB2273"
|
|
94
|
+
},
|
|
95
|
+
"eu-ai-act": {
|
|
96
|
+
"id": "eu-ai-act",
|
|
97
|
+
"name": "EU AI Act (Children)",
|
|
98
|
+
"description": "15 rules for EU AI Act compliance in children's AI systems — risk management (Art. 9), transparency (Art. 13), and constitutional AI principles.",
|
|
99
|
+
"jurisdiction": "EU",
|
|
100
|
+
"jurisdiction_level": "supranational",
|
|
101
|
+
"is_free": false,
|
|
102
|
+
"effective_date": "2026-08-01",
|
|
103
|
+
"source_url": "https://artificialintelligenceact.eu/"
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
"rules": [
|
|
107
|
+
{
|
|
108
|
+
"id": "coppa-auth-001",
|
|
109
|
+
"name": "Unverified Social Login Providers",
|
|
110
|
+
"severity": "critical",
|
|
111
|
+
"confidence": "low",
|
|
112
|
+
"category": "auth",
|
|
113
|
+
"description": "Social login (Google, Facebook, Twitter) without age gating is prohibited for child-directed apps",
|
|
114
|
+
"patterns": [
|
|
115
|
+
{ "pattern": "signInWithPopup\\s*\\(\\s*\\w+\\s*,\\s*['\"](google|facebook|twitter|github)['\"]", "flags": "gi" },
|
|
116
|
+
{ "pattern": "signInWithPopup\\s*\\(\\s*['\"](google|facebook|twitter|github)['\"]", "flags": "gi" },
|
|
117
|
+
{ "pattern": "signInWithPopup\\s*\\(\\s*\\w+\\s*,\\s*\\w+\\s*\\)", "flags": "gi" },
|
|
118
|
+
{ "pattern": "firebase\\.auth\\(\\)\\s*\\.\\s*signInWithPopup", "flags": "gi" },
|
|
119
|
+
{ "pattern": "passport\\.authenticate\\s*\\(\\s*['\"](google|facebook|twitter)['\"]", "flags": "gi" },
|
|
120
|
+
{ "pattern": "SOCIALACCOUNT_PROVIDERS\\s*=\\s*\\{[^}]*(?:google|facebook|twitter|github)", "flags": "gi" },
|
|
121
|
+
{ "pattern": "SOCIAL_AUTH_(?:GOOGLE|FACEBOOK|TWITTER|GITHUB)_(?:KEY|SECRET)", "flags": "gi" },
|
|
122
|
+
{ "pattern": "make_(?:google|facebook|twitter|github)_blueprint\\s*\\(", "flags": "gi" },
|
|
123
|
+
{ "pattern": "oauth\\.register\\s*\\(\\s*['\"](?:google|facebook|twitter|github)['\"]", "flags": "gi" },
|
|
124
|
+
{ "pattern": "goth\\.UseProviders\\s*\\(", "flags": "gi" },
|
|
125
|
+
{ "pattern": "\\.oauth2Login\\s*\\(\\s*\\)", "flags": "gi" },
|
|
126
|
+
{ "pattern": "ClientRegistration\\.withRegistrationId\\s*\\(\\s*['\"](?:google|facebook|twitter|github)['\"]", "flags": "gi" },
|
|
127
|
+
{ "pattern": "Firebase\\.auth\\.signInWithCredential", "flags": "gi" },
|
|
128
|
+
{ "pattern": "GoogleSignIn\\.getClient\\s*\\(", "flags": "gi" },
|
|
129
|
+
{ "pattern": "LoginManager\\.getInstance\\s*\\(\\s*\\)\\s*\\.logIn", "flags": "gi" }
|
|
130
|
+
],
|
|
131
|
+
"fix_suggestion": "Wrap the auth call in a conditional check for user.age >= 13 or use signInWithParentEmail() for children",
|
|
132
|
+
"penalty": "$51,744 per violation",
|
|
133
|
+
"languages": ["typescript", "javascript", "python", "go", "java", "kotlin", "swift"],
|
|
134
|
+
"packs": ["coppa"],
|
|
135
|
+
"fixability": "guided",
|
|
136
|
+
"transform_type": null,
|
|
137
|
+
"scaffold_id": "age-gate-auth",
|
|
138
|
+
"guidance_url": null
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"id": "coppa-data-002",
|
|
142
|
+
"name": "PII Collection in URL Parameters",
|
|
143
|
+
"severity": "high",
|
|
144
|
+
"confidence": "medium",
|
|
145
|
+
"category": "data",
|
|
146
|
+
"description": "Email, name, DOB, or phone in GET request URLs exposes PII in logs",
|
|
147
|
+
"patterns": [
|
|
148
|
+
{ "pattern": "(?<!(?:test|spec|mock|fixture|example|__test__|__mock__|__fixture__)[^\\n]{0,50})(\\?|&)(email|first_?name|last_?name|dob|phone|birthdate)=", "flags": "gi" },
|
|
149
|
+
{ "pattern": "axios\\.get\\s*\\(\\s*[`'\"]https?://[^\\s]*\\?[^`'\"]*(?:email|first_?name|last_?name|dob|phone|birthdate|birth_?date|ssn|username)=[^`'\"]*\\$\\{", "flags": "gi" },
|
|
150
|
+
{ "pattern": "fetch\\s*\\(\\s*[`'\"]https?://[^\\s]*\\?[^`'\"]*(?:email|first_?name|last_?name|dob|phone|birthdate|birth_?date|ssn|username)=[^`'\"]*\\$\\{", "flags": "gi" },
|
|
151
|
+
{ "pattern": "\\?[^'\"`\\s]*\\$\\{[^}]*(?:\\.email|\\.firstName|\\.lastName|\\.dob|\\.phone|\\.birthdate|\\.ssn)[^}]*\\}", "flags": "gi" }
|
|
152
|
+
],
|
|
153
|
+
"fix_suggestion": "Switch to POST method and move PII to request body",
|
|
154
|
+
"penalty": "$51,744 per violation",
|
|
155
|
+
"languages": ["typescript", "javascript", "python", "java", "swift"],
|
|
156
|
+
"packs": ["coppa"],
|
|
157
|
+
"fixability": "guided",
|
|
158
|
+
"transform_type": null,
|
|
159
|
+
"scaffold_id": "pii-sanitizer",
|
|
160
|
+
"guidance_url": null
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
"id": "coppa-tracking-003",
|
|
164
|
+
"name": "Third-Party Ad Trackers",
|
|
165
|
+
"severity": "critical",
|
|
166
|
+
"confidence": "low",
|
|
167
|
+
"category": "tracking",
|
|
168
|
+
"description": "Facebook Pixel, Google Analytics, or other ad trackers without child_directed_treatment flag",
|
|
169
|
+
"patterns": [
|
|
170
|
+
{ "pattern": "fbq\\s*\\(\\s*['\"]init['\"]", "flags": "gi" },
|
|
171
|
+
{ "pattern": "ga\\s*\\(\\s*['\"]create['\"]", "flags": "gi" },
|
|
172
|
+
{ "pattern": "adsbygoogle", "flags": "gi" },
|
|
173
|
+
{ "pattern": "gtag\\s*\\(\\s*['\"]config['\"]", "flags": "gi" },
|
|
174
|
+
{ "pattern": "google-analytics\\.com/analytics\\.js", "flags": "gi" }
|
|
175
|
+
],
|
|
176
|
+
"fix_suggestion": "Add \"child_directed_treatment\": true or \"restrictDataProcessing\": true to SDK initialization",
|
|
177
|
+
"penalty": "$51,744 per violation",
|
|
178
|
+
"languages": ["typescript", "javascript", "html"],
|
|
179
|
+
"packs": ["coppa"],
|
|
180
|
+
"fixability": "guided",
|
|
181
|
+
"transform_type": null,
|
|
182
|
+
"scaffold_id": "remove-tracker",
|
|
183
|
+
"guidance_url": null
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
"id": "coppa-geo-004",
|
|
187
|
+
"name": "Precise Geolocation Collection",
|
|
188
|
+
"severity": "high",
|
|
189
|
+
"confidence": "low",
|
|
190
|
+
"category": "geo",
|
|
191
|
+
"description": "High-accuracy geolocation without parental consent is prohibited",
|
|
192
|
+
"patterns": [
|
|
193
|
+
{ "pattern": "navigator\\.geolocation\\.getCurrentPosition", "flags": "gi" },
|
|
194
|
+
{ "pattern": "navigator\\.geolocation\\.watchPosition", "flags": "gi" },
|
|
195
|
+
{ "pattern": "CLLocationManager\\.startUpdatingLocation\\(\\)", "flags": "gi" },
|
|
196
|
+
{ "pattern": "locationServices\\.requestLocation", "flags": "gi" },
|
|
197
|
+
{ "pattern": "LocationManager\\s*\\.\\s*requestLocationUpdates\\s*\\(", "flags": "gi" },
|
|
198
|
+
{ "pattern": "FusedLocationProviderClient|fusedLocationClient\\s*\\.\\s*(?:requestLocationUpdates|getLastLocation|getCurrentLocation)", "flags": "gi" },
|
|
199
|
+
{ "pattern": "LocationRequest\\.create\\s*\\(\\s*\\)\\s*\\.\\s*setPriority\\s*\\(\\s*LocationRequest\\.PRIORITY_HIGH_ACCURACY", "flags": "gi" },
|
|
200
|
+
{ "pattern": "LocationRequest\\.Builder\\s*\\(\\s*Priority\\.PRIORITY_HIGH_ACCURACY", "flags": "gi" },
|
|
201
|
+
{ "pattern": "geocoder\\.(?:ip|google|osm|mapquest)\\s*\\(", "flags": "gi" },
|
|
202
|
+
{ "pattern": "(?:Nominatim|GoogleV3|Bing)\\s*\\([^)]*\\)\\s*\\.(?:geocode|reverse)", "flags": "gi" },
|
|
203
|
+
{ "pattern": "android\\.permission\\.ACCESS_FINE_LOCATION", "flags": "gi" }
|
|
204
|
+
],
|
|
205
|
+
"fix_suggestion": "Downgrade accuracy to kCLLocationAccuracyThreeKilometers or require parental consent",
|
|
206
|
+
"penalty": "$51,744 per violation",
|
|
207
|
+
"languages": ["typescript", "javascript", "swift", "kotlin", "java", "python", "xml"],
|
|
208
|
+
"packs": ["coppa"],
|
|
209
|
+
"fixability": "guided",
|
|
210
|
+
"transform_type": null,
|
|
211
|
+
"scaffold_id": "remove-geo",
|
|
212
|
+
"guidance_url": null
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
"id": "coppa-retention-005",
|
|
216
|
+
"name": "Missing Data Retention Policy",
|
|
217
|
+
"severity": "medium",
|
|
218
|
+
"confidence": "medium",
|
|
219
|
+
"category": "retention",
|
|
220
|
+
"description": "User schemas containing PII fields must have deleted_at, expiration_date, or TTL index for data retention",
|
|
221
|
+
"patterns": [
|
|
222
|
+
{ "pattern": "new\\s+Schema\\s*\\(\\s*\\{[^{}]*(?:email|password|username|phone|dob|birth|firstName|lastName|first_name|last_name|fullName|full_name|displayName|display_name|address|ssn)[^{}]*\\}", "flags": "gi" },
|
|
223
|
+
{ "pattern": "class\\s+(?:User|Child|Student|Profile|Account|Member)\\w*\\s*\\(\\s*models\\.Model\\s*\\)", "flags": "gi" },
|
|
224
|
+
{ "pattern": "class\\s+(?:User|Child|Student|Profile|Account|Member)\\w*\\s*\\(\\s*(?:Base|db\\.Model)\\s*\\)", "flags": "gi" },
|
|
225
|
+
{ "pattern": "type\\s+(?:User|Child|Student|Profile|Account|Member)\\w*\\s+struct\\s*\\{", "flags": "gi" },
|
|
226
|
+
{ "pattern": "@Entity[\\s\\S]*?class\\s+(?:User|Child|Student|Profile|Account|Member)", "flags": "gi" },
|
|
227
|
+
{ "pattern": "data\\s+class\\s+(?:User|Child|Student|Profile|Account|Member)\\w*\\s*\\(", "flags": "gi" }
|
|
228
|
+
],
|
|
229
|
+
"fix_suggestion": "Add deleted_at column, expiration_date field, or TTL index to database schema",
|
|
230
|
+
"penalty": "Regulatory audit failure",
|
|
231
|
+
"languages": ["typescript", "javascript", "python", "go", "java", "kotlin", "sql"],
|
|
232
|
+
"packs": ["coppa"],
|
|
233
|
+
"fixability": "guided",
|
|
234
|
+
"transform_type": null,
|
|
235
|
+
"scaffold_id": "retention-policy",
|
|
236
|
+
"guidance_url": null
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
"id": "coppa-sec-006",
|
|
240
|
+
"name": "Unencrypted PII Transmission",
|
|
241
|
+
"severity": "critical",
|
|
242
|
+
"confidence": "medium",
|
|
243
|
+
"category": "security",
|
|
244
|
+
"description": "HTTP transmission of PII exposes data in transit. All API endpoints handling personal information must use HTTPS.",
|
|
245
|
+
"patterns": [
|
|
246
|
+
{ "pattern": "http://(?!localhost|127\\.0\\.0\\.1|0\\.0\\.0\\.0|\\[::1\\]|10\\.|192\\.168\\.|172\\.(?:1[6-9]|2[0-9]|3[01]))[^\\s]*(/api/|/login|/user|/register|/profile)", "flags": "gi" },
|
|
247
|
+
{ "pattern": "axios\\.get\\s*\\(\\s*['\"]http://(?!localhost|127\\.0\\.0\\.1)", "flags": "gi" },
|
|
248
|
+
{ "pattern": "fetch\\s*\\(\\s*['\"]http://(?!localhost|127\\.0\\.0\\.1)", "flags": "gi" },
|
|
249
|
+
{ "pattern": "http://(?!localhost|127\\.0\\.0\\.1)[^\\s]*email[^\\s]*", "flags": "gi" }
|
|
250
|
+
],
|
|
251
|
+
"fix_suggestion": "Replace http:// with https:// for all API endpoints and resources",
|
|
252
|
+
"penalty": "Security breach liability + COPPA penalties",
|
|
253
|
+
"languages": ["typescript", "javascript", "python", "java", "swift"],
|
|
254
|
+
"packs": ["coppa"],
|
|
255
|
+
"fixability": "auto",
|
|
256
|
+
"transform_type": "url-upgrade",
|
|
257
|
+
"scaffold_id": null,
|
|
258
|
+
"guidance_url": null
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
"id": "coppa-audio-007",
|
|
262
|
+
"name": "Unauthorized Audio Recording",
|
|
263
|
+
"severity": "high",
|
|
264
|
+
"confidence": "low",
|
|
265
|
+
"category": "audio",
|
|
266
|
+
"description": "Audio recording without explicit user consent is prohibited. COPPA 2.0 clarifies voice prints as biometric data.",
|
|
267
|
+
"patterns": [
|
|
268
|
+
{ "pattern": "getUserMedia\\s*\\(\\s*\\{[^}]*audio\\s*:\\s*true[^}]*\\}", "flags": "gi" },
|
|
269
|
+
{ "pattern": "getUserMedia\\s*\\(\\s*\\{\\s*audio\\s*\\}", "flags": "gi" },
|
|
270
|
+
{ "pattern": "getUserMedia\\s*\\(\\s*\\{\\s*audio\\s*,", "flags": "gi" },
|
|
271
|
+
{ "pattern": "AVAudioSession\\s*\\.\\s*sharedInstance", "flags": "gi" },
|
|
272
|
+
{ "pattern": "AVAudioRecorder\\s*\\(", "flags": "gi" },
|
|
273
|
+
{ "pattern": "new\\s+AudioRecord\\s*\\(", "flags": "gi" },
|
|
274
|
+
{ "pattern": "new\\s+MediaRecorder\\s*\\(", "flags": "gi" }
|
|
275
|
+
],
|
|
276
|
+
"fix_suggestion": "Wrap audio recording in click handler and add parental consent check",
|
|
277
|
+
"penalty": "$51,744 per violation",
|
|
278
|
+
"languages": ["typescript", "javascript", "swift", "kotlin"],
|
|
279
|
+
"packs": ["coppa"],
|
|
280
|
+
"fixability": "guided",
|
|
281
|
+
"transform_type": null,
|
|
282
|
+
"scaffold_id": "consent-audio",
|
|
283
|
+
"guidance_url": null
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
"id": "coppa-ui-008",
|
|
287
|
+
"name": "Missing Privacy Policy on Registration",
|
|
288
|
+
"severity": "medium",
|
|
289
|
+
"confidence": "medium",
|
|
290
|
+
"category": "ui",
|
|
291
|
+
"description": "Registration forms collecting PII must include a clear link to the privacy policy",
|
|
292
|
+
"patterns": [
|
|
293
|
+
{ "pattern": "(?<!(?:interface|type|import|from|require|mock|Mock|jest\\.fn)\\s{0,10})\\b(?!Admin|Teacher|Staff|Instructor|Educator|Parent|Guardian)(?:SignUp|Register|Registration|CreateAccount)Form\\b(?!\\s*(?:\\{|<|\\||&|extends|implements))", "flags": "gi" },
|
|
294
|
+
{ "pattern": "(?<!(?:import|from|require|mock|type|interface)\\s{0,10})\\b(?!admin[-_]?|teacher[-_]?|staff[-_]?|instructor[-_]?|parent[-_]?)(?:sign[-_]?up|register|registration|create[-_]?account)[-_]form\\b(?!\\s*(?:type|interface|schema))", "flags": "gi" },
|
|
295
|
+
{ "pattern": "<form[^>]*(?:id|class|name)\\s*=\\s*[\"'][^\"']*(?!admin|teacher|staff|instructor|educator|parent|guardian)(?:register|signup|sign[-_]up|create[-_]account)[^\"']*[\"']", "flags": "gi" }
|
|
296
|
+
],
|
|
297
|
+
"fix_suggestion": "Add <a href=\"/privacy\">Privacy Policy</a> link to registration form footer",
|
|
298
|
+
"penalty": "Compliance failure",
|
|
299
|
+
"languages": ["typescript", "javascript", "html", "tsx", "jsx", "php"],
|
|
300
|
+
"packs": ["coppa"],
|
|
301
|
+
"fixability": "guided",
|
|
302
|
+
"transform_type": null,
|
|
303
|
+
"scaffold_id": "privacy-link",
|
|
304
|
+
"guidance_url": null
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
"id": "coppa-flow-009",
|
|
308
|
+
"name": "Direct Contact Collection Without Parent Context",
|
|
309
|
+
"severity": "high",
|
|
310
|
+
"confidence": "high",
|
|
311
|
+
"category": "flow",
|
|
312
|
+
"description": "Forms collecting child email/phone must also require parent email for consent verification",
|
|
313
|
+
"patterns": [
|
|
314
|
+
{ "pattern": "(child_email|student_email)\\s*:\\s*String", "flags": "gi" },
|
|
315
|
+
{ "pattern": "(child_email|student_email|kid_email)\\s*=", "flags": "gi" }
|
|
316
|
+
],
|
|
317
|
+
"fix_suggestion": "Make parent_email required when collecting child contact information",
|
|
318
|
+
"penalty": "$51,744 per violation",
|
|
319
|
+
"languages": ["typescript", "javascript", "python"],
|
|
320
|
+
"packs": ["coppa"],
|
|
321
|
+
"fixability": "guided",
|
|
322
|
+
"transform_type": null,
|
|
323
|
+
"scaffold_id": "parent-email",
|
|
324
|
+
"guidance_url": null
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
"id": "coppa-sec-010",
|
|
328
|
+
"name": "Weak Default Student Passwords",
|
|
329
|
+
"severity": "medium",
|
|
330
|
+
"confidence": "high",
|
|
331
|
+
"category": "security",
|
|
332
|
+
"description": "Default passwords like \"password\", \"123456\", or \"changeme\" create security vulnerabilities",
|
|
333
|
+
"patterns": [
|
|
334
|
+
{ "pattern": "(?:const|let|var|export|config|env|setting)\\s*(?:\\w+\\s*=\\s*\\{[^}]*?)?(password|default_pass|temp_password)\\s*[:=]\\s*['\"](123456|password|changeme|student|welcome)['\"]", "flags": "gi" },
|
|
335
|
+
{ "pattern": "defaultPassword:\\s*['\"](123456|password|changeme)['\"]", "flags": "gi" },
|
|
336
|
+
{ "pattern": "initialPassword:\\s*['\"](123456|password)['\"]", "flags": "gi" },
|
|
337
|
+
{ "pattern": "(?:const|let|var|config)\\s*\\w*[Pp]ass\\w*\\s*=\\s*['\"](student123|child123|default)['\"]", "flags": "gi" }
|
|
338
|
+
],
|
|
339
|
+
"fix_suggestion": "Use a secure random string generator for temporary credentials",
|
|
340
|
+
"penalty": "Security audit failure",
|
|
341
|
+
"languages": ["typescript", "javascript", "python", "java", "swift"],
|
|
342
|
+
"packs": ["coppa"],
|
|
343
|
+
"fixability": "auto",
|
|
344
|
+
"transform_type": "remove-default",
|
|
345
|
+
"scaffold_id": null,
|
|
346
|
+
"guidance_url": null
|
|
347
|
+
},
|
|
348
|
+
{
|
|
349
|
+
"id": "coppa-ext-011",
|
|
350
|
+
"name": "Unmoderated Third-Party Chat",
|
|
351
|
+
"severity": "high",
|
|
352
|
+
"confidence": "medium",
|
|
353
|
+
"category": "external",
|
|
354
|
+
"description": "Third-party chat widgets (Intercom, Zendesk, Drift) allow children to disclose PII freely",
|
|
355
|
+
"patterns": [
|
|
356
|
+
{ "pattern": "intercom\\.init", "flags": "gi" },
|
|
357
|
+
{ "pattern": "zendesk\\.init", "flags": "gi" },
|
|
358
|
+
{ "pattern": "drift\\.init", "flags": "gi" },
|
|
359
|
+
{ "pattern": "<script[^>]+src=['\"][^'\"]*intercom", "flags": "gi" },
|
|
360
|
+
{ "pattern": "<script[^>]+src=['\"][^'\"]*(zendesk|zdassets)", "flags": "gi" },
|
|
361
|
+
{ "pattern": "Freshdesk|FreshChat", "flags": "gi" }
|
|
362
|
+
],
|
|
363
|
+
"fix_suggestion": "Disable chat widget for unauthenticated or under-13 users via conditional rendering",
|
|
364
|
+
"penalty": "$51,744 per violation",
|
|
365
|
+
"languages": ["typescript", "javascript", "html"],
|
|
366
|
+
"packs": ["coppa"],
|
|
367
|
+
"fixability": "guided",
|
|
368
|
+
"transform_type": null,
|
|
369
|
+
"scaffold_id": "chat-moderation",
|
|
370
|
+
"guidance_url": null
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
"id": "coppa-bio-012",
|
|
374
|
+
"name": "Biometric Data Collection",
|
|
375
|
+
"severity": "critical",
|
|
376
|
+
"confidence": "medium",
|
|
377
|
+
"category": "biometric",
|
|
378
|
+
"description": "Face recognition, voice prints, or gait analysis requires explicit parental consent. COPPA 2.0 explicitly classifies biometrics as PI.",
|
|
379
|
+
"patterns": [
|
|
380
|
+
{ "pattern": "(?:import\\s+.*from\\s+['\"]face-api\\.js['\"]|require\\s*\\(\\s*['\"]face-api\\.js['\"]\\s*\\))", "flags": "gi" },
|
|
381
|
+
{ "pattern": "LocalAuthentication.*evaluatePolicy", "flags": "gi" },
|
|
382
|
+
{ "pattern": "FaceID|TouchID", "flags": "gi" },
|
|
383
|
+
{ "pattern": "biometricAuth|BiometricAuth", "flags": "g" },
|
|
384
|
+
{ "pattern": "voicePrint|VoicePrint", "flags": "g" },
|
|
385
|
+
{ "pattern": "livenessCheck|LivenessCheck", "flags": "g" },
|
|
386
|
+
{ "pattern": "FaceMatcher|FaceDetector|FaceRecognizer", "flags": "g" }
|
|
387
|
+
],
|
|
388
|
+
"fix_suggestion": "Ensure biometric data remains local-only (on-device) or obtain verifiable parental consent",
|
|
389
|
+
"penalty": "$51,744 per violation",
|
|
390
|
+
"languages": ["typescript", "javascript", "swift", "kotlin"],
|
|
391
|
+
"packs": ["coppa"],
|
|
392
|
+
"fixability": "guided",
|
|
393
|
+
"transform_type": null,
|
|
394
|
+
"scaffold_id": "consent-biometric",
|
|
395
|
+
"guidance_url": null
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
"id": "coppa-notif-013",
|
|
399
|
+
"name": "Direct Push Notifications Without Consent",
|
|
400
|
+
"severity": "medium",
|
|
401
|
+
"confidence": "low",
|
|
402
|
+
"category": "notification",
|
|
403
|
+
"description": "Push notifications are \"Online Contact Info\" under COPPA 2.0. Direct notifications to children require parental consent.",
|
|
404
|
+
"patterns": [
|
|
405
|
+
{ "pattern": "FirebaseMessaging\\.subscribeToTopic", "flags": "gi" },
|
|
406
|
+
{ "pattern": "OneSignal\\.promptForPushNotifications", "flags": "gi" },
|
|
407
|
+
{ "pattern": "sendPushNotification\\s*\\(", "flags": "gi" },
|
|
408
|
+
{ "pattern": "fcm\\.send\\s*\\(", "flags": "gi" },
|
|
409
|
+
{ "pattern": "PushManager\\.subscribe\\s*\\(", "flags": "gi" },
|
|
410
|
+
{ "pattern": "Notification\\.requestPermission", "flags": "gi" },
|
|
411
|
+
{ "pattern": "new\\s+Notification\\s*\\(", "flags": "gi" }
|
|
412
|
+
],
|
|
413
|
+
"fix_suggestion": "Gate push notification subscription behind parental dashboard setting",
|
|
414
|
+
"penalty": "$51,744 per violation",
|
|
415
|
+
"languages": ["typescript", "javascript", "swift", "kotlin"],
|
|
416
|
+
"packs": ["coppa"],
|
|
417
|
+
"fixability": "guided",
|
|
418
|
+
"transform_type": null,
|
|
419
|
+
"scaffold_id": "consent-notif",
|
|
420
|
+
"guidance_url": null
|
|
421
|
+
},
|
|
422
|
+
{
|
|
423
|
+
"id": "coppa-ugc-014",
|
|
424
|
+
"name": "UGC Upload Without PII Filter",
|
|
425
|
+
"severity": "high",
|
|
426
|
+
"confidence": "medium",
|
|
427
|
+
"category": "ugc",
|
|
428
|
+
"description": "Text areas for \"bio\", \"about me\", or comments must pass through PII scrubbing before database storage",
|
|
429
|
+
"patterns": [
|
|
430
|
+
{ "pattern": "<textarea[^>]*placeholder=[\"'](?:bio|about me|describe yourself)[^\"']*[\"']", "flags": "gi" },
|
|
431
|
+
{ "pattern": "user\\.bio\\s*=", "flags": "gi" },
|
|
432
|
+
{ "pattern": "aboutMe\\s*=", "flags": "gi" },
|
|
433
|
+
{ "pattern": "(?:submit|save|post)Comment\\s*\\((?![^)]*(?:admin|moderate|internal|review))", "flags": "gi" },
|
|
434
|
+
{ "pattern": "(?:saveBio|updateBio)\\s*\\((?![^)]*(?:admin|moderate|internal))", "flags": "gi" },
|
|
435
|
+
{ "pattern": "(?<!admin|Admin|moderate|Moderate)(?:commentForm.*submit|handleCommentSubmit)", "flags": "gi" }
|
|
436
|
+
],
|
|
437
|
+
"fix_suggestion": "Add middleware hook for PII scrubbing (regex or AWS Comprehend) before database storage",
|
|
438
|
+
"penalty": "$51,744 per violation",
|
|
439
|
+
"languages": ["typescript", "javascript", "python"],
|
|
440
|
+
"packs": ["coppa"],
|
|
441
|
+
"fixability": "guided",
|
|
442
|
+
"transform_type": null,
|
|
443
|
+
"scaffold_id": "pii-filter",
|
|
444
|
+
"guidance_url": null
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
"id": "coppa-sec-015",
|
|
448
|
+
"name": "Reflected XSS Risk",
|
|
449
|
+
"severity": "medium",
|
|
450
|
+
"confidence": "medium",
|
|
451
|
+
"category": "security",
|
|
452
|
+
"description": "DangerouslySetInnerHTML or innerHTML with user-controlled content creates XSS vulnerabilities",
|
|
453
|
+
"patterns": [
|
|
454
|
+
{ "pattern": "dangerouslySetInnerHTML\\s*=\\s*\\{\\s*\\{\\s*__html\\s*:\\s*(?!['\"]<)[^}]*\\}\\s*\\}", "flags": "gi" },
|
|
455
|
+
{ "pattern": "\\.innerHTML\\s*=\\s*\\$\\{", "flags": "gi" },
|
|
456
|
+
{ "pattern": "\\.innerHTML\\s*=\\s*(?!['\"]?\\s*['\"]?\\s*;)(?!.*[Ll]ocal(?:ize|ization))(?!.*styleContent)[^;]*\\b(?:user|input|query|param|req\\.|request\\.|body\\.|data\\.)\\w*", "flags": "gi" },
|
|
457
|
+
{ "pattern": "\\.html\\s*\\(\\s*(?:user|req\\.|request\\.|params?\\.)", "flags": "gi" },
|
|
458
|
+
{ "pattern": "v-html\\s*=\\s*[\"']?(?!.*sanitize)", "flags": "gi" }
|
|
459
|
+
],
|
|
460
|
+
"fix_suggestion": "Use standard JSX rendering or DOMPurify before setting HTML content. Note: vendor/bundled libraries may trigger this rule — use .haloignore to suppress.",
|
|
461
|
+
"penalty": "Security failure",
|
|
462
|
+
"languages": ["typescript", "javascript", "tsx", "jsx", "vue"],
|
|
463
|
+
"packs": ["coppa"],
|
|
464
|
+
"fixability": "auto",
|
|
465
|
+
"transform_type": "sanitize-input",
|
|
466
|
+
"scaffold_id": null,
|
|
467
|
+
"guidance_url": null
|
|
468
|
+
},
|
|
469
|
+
{
|
|
470
|
+
"id": "coppa-cookies-016",
|
|
471
|
+
"name": "Missing Cookie Notice",
|
|
472
|
+
"severity": "low",
|
|
473
|
+
"confidence": "medium",
|
|
474
|
+
"category": "cookies",
|
|
475
|
+
"description": "Cookies or localStorage storing tracking data or PII requires a consent banner",
|
|
476
|
+
"patterns": [
|
|
477
|
+
{ "pattern": "document\\.cookie\\s*=\\s*[^;]*(?:user|email|name|token|session|track|id|uid|analytics)", "flags": "gi" },
|
|
478
|
+
{ "pattern": "localStorage\\.setItem\\s*\\(\\s*['\"][^'\"]*(?:user_?id|user_?email|user_?token|auth_?token|session_?token|track_?id|tracking|login_?token|uid|analytics_?id|user_?data|user_?profile)[^'\"]*['\"]", "flags": "gi" },
|
|
479
|
+
{ "pattern": "sessionStorage\\.setItem\\s*\\(\\s*['\"][^'\"]*(?:user_?id|user_?email|user_?token|auth_?token|session_?token|track_?id|tracking|login_?token|uid|analytics_?id|user_?data|user_?profile)[^'\"]*['\"]", "flags": "gi" },
|
|
480
|
+
{ "pattern": "\\.set_cookie\\s*\\(\\s*['\"][^'\"]*(?:user|email|token|session|track|auth|login|uid|analytics)[^'\"]*['\"]", "flags": "gi" },
|
|
481
|
+
{ "pattern": "http\\.SetCookie\\s*\\(\\s*\\w+\\s*,\\s*&http\\.Cookie\\s*\\{", "flags": "gi" },
|
|
482
|
+
{ "pattern": "\\.addCookie\\s*\\(\\s*new\\s+Cookie\\s*\\(", "flags": "gi" },
|
|
483
|
+
{ "pattern": "ResponseCookie\\.from\\s*\\(", "flags": "gi" },
|
|
484
|
+
{ "pattern": "(?:set_cookie|SetCookie|addCookie|add_cookie)\\s*\\([^)]*(?:user|email|token|session|track|auth|uid|analytics)", "flags": "gi" }
|
|
485
|
+
],
|
|
486
|
+
"fix_suggestion": "Add a cookie consent banner component before setting tracking or PII cookies",
|
|
487
|
+
"penalty": "Compliance warning",
|
|
488
|
+
"languages": ["typescript", "javascript", "python", "go", "java", "kotlin"],
|
|
489
|
+
"packs": ["coppa"],
|
|
490
|
+
"fixability": "guided",
|
|
491
|
+
"transform_type": null,
|
|
492
|
+
"scaffold_id": "consent-cookies",
|
|
493
|
+
"guidance_url": null
|
|
494
|
+
},
|
|
495
|
+
{
|
|
496
|
+
"id": "coppa-ext-017",
|
|
497
|
+
"name": "Unwarned External Links",
|
|
498
|
+
"severity": "medium",
|
|
499
|
+
"confidence": "medium",
|
|
500
|
+
"category": "external",
|
|
501
|
+
"description": "External links in child-facing views should trigger a \"You are leaving...\" modal",
|
|
502
|
+
"patterns": [
|
|
503
|
+
{ "pattern": "<a[^>]+href=[\"']https?://(?!.*(?:privacy|terms|legal|tos|policy|consent|support|help|docs|documentation))[^\"']+[\"'][^>]*target=[\"']_blank[\"'][^>]*>", "flags": "gi" },
|
|
504
|
+
{ "pattern": "window\\.open\\s*\\(\\s*['\"]https?://(?!.*(?:privacy|terms|legal|tos|policy|support|help|docs|documentation|faq|about))", "flags": "gi" }
|
|
505
|
+
],
|
|
506
|
+
"fix_suggestion": "Wrap external links in SafeLink component with warning modal",
|
|
507
|
+
"penalty": "Warning",
|
|
508
|
+
"languages": ["typescript", "javascript", "html", "tsx", "jsx"],
|
|
509
|
+
"packs": ["coppa"],
|
|
510
|
+
"fixability": "guided",
|
|
511
|
+
"transform_type": null,
|
|
512
|
+
"scaffold_id": "exit-modal",
|
|
513
|
+
"guidance_url": null
|
|
514
|
+
},
|
|
515
|
+
{
|
|
516
|
+
"id": "coppa-analytics-018",
|
|
517
|
+
"name": "Mapping PII to Analytics User IDs",
|
|
518
|
+
"severity": "high",
|
|
519
|
+
"confidence": "medium",
|
|
520
|
+
"category": "analytics",
|
|
521
|
+
"description": "Passing email, name, or phone to analytics.identify() exposes PII to third parties",
|
|
522
|
+
"patterns": [
|
|
523
|
+
{ "pattern": "analytics\\.identify\\s*\\([^)]*email", "flags": "gi" },
|
|
524
|
+
{ "pattern": "mixpanel\\.identify.*email", "flags": "gi" },
|
|
525
|
+
{ "pattern": "segment\\.identify.*email", "flags": "gi" },
|
|
526
|
+
{ "pattern": "amplitude\\.identify.*email", "flags": "gi" },
|
|
527
|
+
{ "pattern": "identify\\s*\\(\\s*\\{[^}]*(?:email|name|phone)[^}]*\\}", "flags": "gi" },
|
|
528
|
+
{ "pattern": "analytics\\.identify\\s*\\(\\s*\\w+\\s*,\\s*\\{[^}]*(?:email|name|phone)", "flags": "gi" },
|
|
529
|
+
{ "pattern": "mp\\.people_set\\s*\\([^)]*(?:email|\\$email|name|phone)", "flags": "gi" },
|
|
530
|
+
{ "pattern": "analytics\\.Enqueue\\s*\\(\\s*analytics\\.Identify\\s*\\{[^}]*(?:Email|Name|Phone)", "flags": "gi" },
|
|
531
|
+
{ "pattern": "Amplitude\\.getInstance\\s*\\(\\s*\\)\\s*\\.setUserId\\s*\\([^)]*email", "flags": "gi" },
|
|
532
|
+
{ "pattern": "MixpanelAPI\\.\\w*identify\\s*\\([^)]*email", "flags": "gi" },
|
|
533
|
+
{ "pattern": "FirebaseAnalytics\\.setUserId\\s*\\([^)]*(?:email|name)", "flags": "gi" },
|
|
534
|
+
{ "pattern": "(?:setUserId|set_user_id)\\s*\\([^)]*(?:email|\\.name|phone)", "flags": "gi" }
|
|
535
|
+
],
|
|
536
|
+
"fix_suggestion": "Hash user ID and omit email/name from analytics payload",
|
|
537
|
+
"penalty": "$51,744 per violation",
|
|
538
|
+
"languages": ["typescript", "javascript", "python", "go", "java", "kotlin"],
|
|
539
|
+
"packs": ["coppa"],
|
|
540
|
+
"fixability": "guided",
|
|
541
|
+
"transform_type": null,
|
|
542
|
+
"scaffold_id": "anonymize-analytics",
|
|
543
|
+
"guidance_url": null
|
|
544
|
+
},
|
|
545
|
+
{
|
|
546
|
+
"id": "coppa-edu-019",
|
|
547
|
+
"name": "Missing Teacher/School Verification",
|
|
548
|
+
"severity": "medium",
|
|
549
|
+
"confidence": "low",
|
|
550
|
+
"category": "education",
|
|
551
|
+
"description": "Teacher accounts using generic email (@gmail.com) bypass \"School Official\" consent exception",
|
|
552
|
+
"patterns": [
|
|
553
|
+
{ "pattern": "(?:teacher|educator)(?:Sign[Uu]p|[Rr]egist(?:er|ration))\\s*(?:\\(|=|:)", "flags": "gi" },
|
|
554
|
+
{ "pattern": "createTeacherAccount|registerTeacher|teacherAuth", "flags": "gi" },
|
|
555
|
+
{ "pattern": "role\\s*(?:=|:)\\s*['\"]teacher['\"].*(?:@gmail|@yahoo|@hotmail)", "flags": "gi" },
|
|
556
|
+
{ "pattern": "isTeacher\\s*&&\\s*!.*\\.edu", "flags": "gi" }
|
|
557
|
+
],
|
|
558
|
+
"fix_suggestion": "Restrict teacher sign-ups to verified EDU domains or require manual approval",
|
|
559
|
+
"penalty": "Loss of School Official consent status",
|
|
560
|
+
"languages": ["typescript", "javascript", "python"],
|
|
561
|
+
"packs": ["coppa"],
|
|
562
|
+
"fixability": "guided",
|
|
563
|
+
"transform_type": null,
|
|
564
|
+
"scaffold_id": "school-verify",
|
|
565
|
+
"guidance_url": null
|
|
566
|
+
},
|
|
567
|
+
{
|
|
568
|
+
"id": "coppa-default-020",
|
|
569
|
+
"name": "Default Public Profile Visibility",
|
|
570
|
+
"severity": "critical",
|
|
571
|
+
"confidence": "medium",
|
|
572
|
+
"category": "defaults",
|
|
573
|
+
"description": "Default profile visibility must be private. COPPA 2.0 requires privacy by design.",
|
|
574
|
+
"patterns": [
|
|
575
|
+
{ "pattern": "(?<!(?:mock|Mock|fake|stub|fixture|seed|example|test|Test|expect|assert|//|\\*)\\s{0,20})isProfileVisible:\\s*true", "flags": "gi" },
|
|
576
|
+
{ "pattern": "(?<!(?:mock|Mock|fake|stub|fixture|seed|example|test|Test|expect|assert|//|\\*)\\s{0,20})(?:profile|user|account|member)[^\\n]{0,30}visibility:\\s*['\"]public['\"]", "flags": "gi" },
|
|
577
|
+
{ "pattern": "(?<!(?:mock|Mock|fake|stub|fixture|seed|example|test|Test|expect|assert|//|\\*)\\s{0,20})defaultPrivacy:\\s*['\"]public['\"]", "flags": "gi" },
|
|
578
|
+
{ "pattern": "(?<!(?:mock|Mock|fake|stub|fixture|seed|example|test|Test|expect|assert|//|\\*)\\s{0,20})isPublic:\\s*true[^}]*(profile|User)", "flags": "gi" },
|
|
579
|
+
{ "pattern": "(?<!(?:mock|Mock|fake|stub|fixture|seed|example|test|Test|expect|assert|//|\\*)\\s{0,20})profileVisibility\\s*=\\s*['\"]?(?:public|Public)['\"]?", "flags": "gi" }
|
|
580
|
+
],
|
|
581
|
+
"fix_suggestion": "Change default visibility to \"private\" or false",
|
|
582
|
+
"penalty": "$51,744 per violation",
|
|
583
|
+
"languages": ["typescript", "javascript", "python", "swift"],
|
|
584
|
+
"packs": ["coppa"],
|
|
585
|
+
"fixability": "auto",
|
|
586
|
+
"transform_type": "set-default",
|
|
587
|
+
"scaffold_id": null,
|
|
588
|
+
"guidance_url": null
|
|
589
|
+
},
|
|
590
|
+
{
|
|
591
|
+
"id": "ETHICAL-001",
|
|
592
|
+
"name": "Infinite Scroll / Endless Feed",
|
|
593
|
+
"severity": "high",
|
|
594
|
+
"confidence": "medium",
|
|
595
|
+
"category": "ethical-design",
|
|
596
|
+
"description": "Infinite scroll exploits lack of impulse control. Children spend 2-3x longer on infinite feeds.",
|
|
597
|
+
"patterns": [
|
|
598
|
+
{ "pattern": "IntersectionObserver[^\\n]*isIntersecting[^\\n]*(?:loadMore|fetchMore|nextPage)", "flags": "gi" },
|
|
599
|
+
{ "pattern": "window\\.addEventListener[^\\n]*['\"]scroll['\"][^\\n]*(?:fetchNext|loadNext|loadMore)", "flags": "gi" },
|
|
600
|
+
{ "pattern": "import[^\\n]*(?:InfiniteScroll|InfiniteLoader|InfiniteList)(?![^\\n]*(?:admin|Admin|table|Table|data))", "flags": "gi" },
|
|
601
|
+
{ "pattern": "<(?:InfiniteScroll|InfiniteLoader)(?![^>]*(?:admin|table|data-table))", "flags": "gi" },
|
|
602
|
+
{ "pattern": "ngx-infinite-scroll", "flags": "gi" },
|
|
603
|
+
{ "pattern": "vue-infinite-loading", "flags": "gi" }
|
|
604
|
+
],
|
|
605
|
+
"fix_suggestion": "Replace infinite scroll with pagination or \"Load More\" buttons to create natural stopping points. Suppress with .haloignore for admin/internal dashboards.",
|
|
606
|
+
"penalty": "Ethical Design Violation",
|
|
607
|
+
"languages": ["typescript", "javascript", "tsx", "jsx", "vue"],
|
|
608
|
+
"packs": ["ethical"],
|
|
609
|
+
"fixability": "flag-only",
|
|
610
|
+
"transform_type": null,
|
|
611
|
+
"scaffold_id": null,
|
|
612
|
+
"guidance_url": "https://docs.runhalo.dev/ethical/infinite-scroll"
|
|
613
|
+
},
|
|
614
|
+
{
|
|
615
|
+
"id": "ETHICAL-002",
|
|
616
|
+
"name": "Streak Pressure Mechanics",
|
|
617
|
+
"severity": "high",
|
|
618
|
+
"confidence": "medium",
|
|
619
|
+
"category": "ethical-design",
|
|
620
|
+
"description": "Streak mechanics use loss aversion to manufacture daily compulsive usage",
|
|
621
|
+
"patterns": [
|
|
622
|
+
{ "pattern": "streak.*>.*0.*loss", "flags": "gi" },
|
|
623
|
+
{ "pattern": "lose.*your.*streak", "flags": "gi" },
|
|
624
|
+
{ "pattern": "streak.*ends.*in", "flags": "gi" },
|
|
625
|
+
{ "pattern": "don'?t.*break.*streak", "flags": "gi" },
|
|
626
|
+
{ "pattern": "dailyStreak", "flags": "gi" },
|
|
627
|
+
{ "pattern": "consecutiveDays", "flags": "gi" }
|
|
628
|
+
],
|
|
629
|
+
"fix_suggestion": "Remove streak loss penalties. Frame progress as cumulative (e.g., \"15 days practiced\") rather than consecutive.",
|
|
630
|
+
"penalty": "Ethical Design Violation",
|
|
631
|
+
"languages": ["typescript", "javascript", "swift", "kotlin"],
|
|
632
|
+
"packs": ["ethical"],
|
|
633
|
+
"fixability": "flag-only",
|
|
634
|
+
"transform_type": null,
|
|
635
|
+
"scaffold_id": null,
|
|
636
|
+
"guidance_url": "https://docs.runhalo.dev/ethical/streak-pressure"
|
|
637
|
+
},
|
|
638
|
+
{
|
|
639
|
+
"id": "ETHICAL-003",
|
|
640
|
+
"name": "Variable Ratio Rewards (Loot Boxes)",
|
|
641
|
+
"severity": "critical",
|
|
642
|
+
"confidence": "medium",
|
|
643
|
+
"category": "ethical-design",
|
|
644
|
+
"description": "Randomized rewards (loot boxes, gacha) exploit gambling psychology in developing brains",
|
|
645
|
+
"patterns": [
|
|
646
|
+
{ "pattern": "Math\\.random\\(\\).*reward", "flags": "gi" },
|
|
647
|
+
{ "pattern": "loot_?box", "flags": "gi" },
|
|
648
|
+
{ "pattern": "gacha", "flags": "gi" },
|
|
649
|
+
{ "pattern": "mystery_?crate", "flags": "gi" },
|
|
650
|
+
{ "pattern": "openCrate", "flags": "gi" },
|
|
651
|
+
{ "pattern": "rarityTable", "flags": "gi" },
|
|
652
|
+
{ "pattern": "dropRates", "flags": "gi" }
|
|
653
|
+
],
|
|
654
|
+
"fix_suggestion": "Replace random rewards with transparent, effort-based rewards. Disclosure of odds is a minimum requirement.",
|
|
655
|
+
"penalty": "Ethical Design Violation",
|
|
656
|
+
"languages": ["typescript", "javascript", "python", "csharp"],
|
|
657
|
+
"packs": ["ethical"],
|
|
658
|
+
"fixability": "flag-only",
|
|
659
|
+
"transform_type": null,
|
|
660
|
+
"scaffold_id": null,
|
|
661
|
+
"guidance_url": "https://docs.runhalo.dev/ethical/variable-rewards"
|
|
662
|
+
},
|
|
663
|
+
{
|
|
664
|
+
"id": "ETHICAL-004",
|
|
665
|
+
"name": "Manipulative Notification Language",
|
|
666
|
+
"severity": "medium",
|
|
667
|
+
"confidence": "medium",
|
|
668
|
+
"category": "ethical-design",
|
|
669
|
+
"description": "User-facing strings using urgency language (\"Hurry!\", \"Missing out\") manipulate children's fear of social exclusion. Only flags text inside string literals or JSX content.",
|
|
670
|
+
"patterns": [
|
|
671
|
+
{ "pattern": "(?:[\"'`>])\\s*[^\"'`<\\n]*?(?:hurry|limited\\s*time|missing\\s*out|don'?t\\s*miss|left\\s*behind)", "flags": "gi" },
|
|
672
|
+
{ "pattern": "(?:[\"'`>])\\s*[^\"'`<\\n]*?everyone\\s*else\\s*is", "flags": "gi" },
|
|
673
|
+
{ "pattern": "(?:[\"'`>])\\s*[^\"'`<\\n]*?last\\s*chance", "flags": "gi" },
|
|
674
|
+
{ "pattern": "(?:[\"'`>])\\s*[^\"'`<\\n]*?running\\s*out(?!\\s*of\\s*(?:memory|disk|space|storage|connections|retries|attempts|time))", "flags": "gi" }
|
|
675
|
+
],
|
|
676
|
+
"fix_suggestion": "Use neutral, informational language. Avoid FOMO (Fear Of Missing Out) triggers.",
|
|
677
|
+
"penalty": "Ethical Design Violation",
|
|
678
|
+
"languages": ["typescript", "javascript", "json", "xml"],
|
|
679
|
+
"packs": ["ethical"],
|
|
680
|
+
"fixability": "flag-only",
|
|
681
|
+
"transform_type": null,
|
|
682
|
+
"scaffold_id": null,
|
|
683
|
+
"guidance_url": "https://docs.runhalo.dev/ethical/manipulative-notifications"
|
|
684
|
+
},
|
|
685
|
+
{
|
|
686
|
+
"id": "ETHICAL-005",
|
|
687
|
+
"name": "Artificial Scarcity / Countdowns",
|
|
688
|
+
"severity": "medium",
|
|
689
|
+
"confidence": "medium",
|
|
690
|
+
"category": "ethical-design",
|
|
691
|
+
"description": "Fake scarcity (\"Only 2 left!\") and countdown timers pressure children into impulsive decisions",
|
|
692
|
+
"patterns": [
|
|
693
|
+
{ "pattern": "(?:sale|offer|deal|promo|discount|purchase|buy|shop|cart|checkout)[^\\n]*CountdownTimer|CountdownTimer[^\\n]*(?:sale|offer|deal|promo|discount|purchase|buy|shop|cart|checkout)", "flags": "gi" },
|
|
694
|
+
{ "pattern": "(?:[\"'`>])\\s*[^\"'`<\\n]*?only\\s*\\d+\\s*left", "flags": "gi" },
|
|
695
|
+
{ "pattern": "(?:[\"'`>])\\s*[^\"'`<\\n]*?offer\\s*ends\\s*in", "flags": "gi" },
|
|
696
|
+
{ "pattern": "(?:[\"'`>])\\s*[^\"'`<\\n]*?selling\\s*fast", "flags": "gi" },
|
|
697
|
+
{ "pattern": "(?:[\"'`>])\\s*[^\"'`<\\n]*?almost\\s*sold\\s*out", "flags": "gi" },
|
|
698
|
+
{ "pattern": "(?:[\"'`>])\\s*[^\"'`<\\n]*?limited\\s*availability", "flags": "gi" }
|
|
699
|
+
],
|
|
700
|
+
"fix_suggestion": "Remove artificial urgency. If an offer expires, state the date calmly without countdown pressure. Suppress with .haloignore for non-commerce timers (quizzes, sessions, deploys).",
|
|
701
|
+
"penalty": "Ethical Design Violation",
|
|
702
|
+
"languages": ["typescript", "javascript", "tsx", "jsx", "html"],
|
|
703
|
+
"packs": ["ethical"],
|
|
704
|
+
"fixability": "flag-only",
|
|
705
|
+
"transform_type": null,
|
|
706
|
+
"scaffold_id": null,
|
|
707
|
+
"guidance_url": "https://docs.runhalo.dev/ethical/artificial-scarcity"
|
|
708
|
+
},
|
|
709
|
+
{
|
|
710
|
+
"id": "AI-AUDIT-001",
|
|
711
|
+
"name": "Placeholder Analytics Script",
|
|
712
|
+
"severity": "high",
|
|
713
|
+
"confidence": "high",
|
|
714
|
+
"category": "ai-audit",
|
|
715
|
+
"description": "AI-generated code frequently includes placeholder analytics (UA-XXXXX, G-XXXXXX, fbq) copied from training data. These may activate real tracking without child_directed_treatment flags.",
|
|
716
|
+
"patterns": [
|
|
717
|
+
{ "pattern": "gtag\\s*\\(\\s*['\"]config['\"]\\s*,\\s*['\"](?:UA-|G-)X{3,}['\"]", "flags": "gi" },
|
|
718
|
+
{ "pattern": "fbq\\s*\\(\\s*['\"]init['\"]\\s*,\\s*['\"](?:0{5,}|1{5,}|X{5,}|YOUR_|PIXEL_ID|123456789)['\"]", "flags": "gi" },
|
|
719
|
+
{ "pattern": "ga\\s*\\(\\s*['\"]create['\"]\\s*,\\s*['\"]UA-(?:0{5,}|X{5,}|YOUR_)['\"]", "flags": "gi" },
|
|
720
|
+
{ "pattern": "['\"](?:UA|G)-(?:XXXXXXX|0000000|YOUR_ID|REPLACE_ME)['\"]", "flags": "gi" },
|
|
721
|
+
{ "pattern": "analytics_id\\s*[:=]\\s*['\"](?:placeholder|test|example|TODO|FIXME)['\"]", "flags": "gi" }
|
|
722
|
+
],
|
|
723
|
+
"fix_suggestion": "Remove placeholder analytics IDs. If analytics are needed, use a COPPA-compliant provider with child_directed_treatment: true.",
|
|
724
|
+
"penalty": "AI-generated compliance risk",
|
|
725
|
+
"languages": ["typescript", "javascript", "html"],
|
|
726
|
+
"packs": ["ai-audit"],
|
|
727
|
+
"fixability": "flag-only",
|
|
728
|
+
"transform_type": null,
|
|
729
|
+
"scaffold_id": null,
|
|
730
|
+
"guidance_url": null
|
|
731
|
+
},
|
|
732
|
+
{
|
|
733
|
+
"id": "AI-AUDIT-002",
|
|
734
|
+
"name": "AI-Generated Hardcoded Secrets",
|
|
735
|
+
"severity": "critical",
|
|
736
|
+
"confidence": "medium",
|
|
737
|
+
"category": "ai-audit",
|
|
738
|
+
"description": "AI coding assistants frequently generate placeholder API keys, tokens, and secrets inline. These may be committed to version control and exposed.",
|
|
739
|
+
"patterns": [
|
|
740
|
+
{ "pattern": "(?:api_?key|apiKey|API_KEY)\\s*[:=]\\s*['\"](?:sk-|pk-|ak-|key-)[a-zA-Z0-9]{10,}['\"]", "flags": "gi" },
|
|
741
|
+
{ "pattern": "(?:secret|SECRET|token|TOKEN)\\s*[:=]\\s*['\"](?!process\\.env)[a-zA-Z0-9_-]{20,}['\"]", "flags": "gi" },
|
|
742
|
+
{ "pattern": "SUPABASE_(?:ANON_KEY|SERVICE_ROLE_KEY)\\s*[:=]\\s*['\"]ey[a-zA-Z0-9_.+-]{30,}['\"]", "flags": "gi" },
|
|
743
|
+
{ "pattern": "FIREBASE_(?:API_KEY|CONFIG)\\s*[:=]\\s*['\"]AI[a-zA-Z0-9_-]{30,}['\"]", "flags": "gi" },
|
|
744
|
+
{ "pattern": "(?:password|passwd|pwd)\\s*[:=]\\s*['\"](?!process\\.env|test|Test|mock|Mock|example|Example|dummy|Dummy|fake|Fake|fixture)[^'\"]{8,}['\"]\\s*(?:,|;|\\})", "flags": "gi" }
|
|
745
|
+
],
|
|
746
|
+
"fix_suggestion": "Move all secrets to environment variables. Use process.env.API_KEY or a secrets manager. Never hardcode credentials.",
|
|
747
|
+
"penalty": "Security exposure — credentials in source code",
|
|
748
|
+
"languages": ["typescript", "javascript", "python", "java"],
|
|
749
|
+
"packs": ["ai-audit"],
|
|
750
|
+
"fixability": "flag-only",
|
|
751
|
+
"transform_type": null,
|
|
752
|
+
"scaffold_id": null,
|
|
753
|
+
"guidance_url": null
|
|
754
|
+
},
|
|
755
|
+
{
|
|
756
|
+
"id": "AI-AUDIT-003",
|
|
757
|
+
"name": "Hallucinated/Placeholder API URLs",
|
|
758
|
+
"severity": "medium",
|
|
759
|
+
"confidence": "high",
|
|
760
|
+
"category": "ai-audit",
|
|
761
|
+
"description": "AI models often generate fake API endpoints (api.example.com, jsonplaceholder, reqres.in) that may be replaced with real endpoints without proper review.",
|
|
762
|
+
"patterns": [
|
|
763
|
+
{ "pattern": "fetch\\s*\\(\\s*['\"]https?://(?:api\\.example\\.com|jsonplaceholder\\.typicode\\.com|reqres\\.in|httpbin\\.org|mockapi\\.io|dummyjson\\.com)[^'\"]*['\"]", "flags": "gi" },
|
|
764
|
+
{ "pattern": "axios\\.\\w+\\s*\\(\\s*['\"]https?://(?:api\\.example\\.com|jsonplaceholder\\.typicode\\.com|reqres\\.in|httpbin\\.org|dummyjson\\.com)[^'\"]*['\"]", "flags": "gi" },
|
|
765
|
+
{ "pattern": "(?:BASE_URL|API_URL|ENDPOINT)\\s*[:=]\\s*['\"]https?://(?:api\\.example\\.com|your-api|my-api|TODO|REPLACE)[^'\"]*['\"]", "flags": "gi" }
|
|
766
|
+
],
|
|
767
|
+
"fix_suggestion": "Replace placeholder URLs with actual endpoints from environment variables. Review all API calls for COPPA data handling compliance.",
|
|
768
|
+
"penalty": "AI-generated placeholder risk",
|
|
769
|
+
"languages": ["typescript", "javascript", "python"],
|
|
770
|
+
"packs": ["ai-audit"],
|
|
771
|
+
"fixability": "flag-only",
|
|
772
|
+
"transform_type": null,
|
|
773
|
+
"scaffold_id": null,
|
|
774
|
+
"guidance_url": null
|
|
775
|
+
},
|
|
776
|
+
{
|
|
777
|
+
"id": "AI-AUDIT-004",
|
|
778
|
+
"name": "Copy-Paste Tracking Boilerplate",
|
|
779
|
+
"severity": "high",
|
|
780
|
+
"confidence": "medium",
|
|
781
|
+
"category": "ai-audit",
|
|
782
|
+
"description": "AI assistants reproduce common analytics setup patterns from training data. These often include user identification, event tracking, and session recording without consent flows.",
|
|
783
|
+
"patterns": [
|
|
784
|
+
{ "pattern": "hotjar\\.init\\s*\\(", "flags": "gi" },
|
|
785
|
+
{ "pattern": "Sentry\\.init\\s*\\(\\s*\\{[^}]*dsn", "flags": "gi" },
|
|
786
|
+
{ "pattern": "LogRocket\\.init\\s*\\(", "flags": "gi" },
|
|
787
|
+
{ "pattern": "FullStory\\.init\\s*\\(", "flags": "gi" },
|
|
788
|
+
{ "pattern": "heap\\.load\\s*\\(", "flags": "gi" },
|
|
789
|
+
{ "pattern": "posthog\\.init\\s*\\(", "flags": "gi" },
|
|
790
|
+
{ "pattern": "amplitude\\.init\\s*\\(", "flags": "gi" },
|
|
791
|
+
{ "pattern": "mixpanel\\.init\\s*\\(", "flags": "gi" },
|
|
792
|
+
{ "pattern": "window\\.clarity\\s*\\(", "flags": "gi" }
|
|
793
|
+
],
|
|
794
|
+
"fix_suggestion": "Remove session recording and analytics initialization unless COPPA consent is obtained. These tools capture keystrokes, mouse movements, and user behavior — all PII for children.",
|
|
795
|
+
"penalty": "Third-party data collection without consent",
|
|
796
|
+
"languages": ["typescript", "javascript", "html"],
|
|
797
|
+
"packs": ["ai-audit"],
|
|
798
|
+
"fixability": "flag-only",
|
|
799
|
+
"transform_type": null,
|
|
800
|
+
"scaffold_id": null,
|
|
801
|
+
"guidance_url": null
|
|
802
|
+
},
|
|
803
|
+
{
|
|
804
|
+
"id": "AI-AUDIT-005",
|
|
805
|
+
"name": "AI-Generated Insecure Defaults",
|
|
806
|
+
"severity": "medium",
|
|
807
|
+
"confidence": "high",
|
|
808
|
+
"category": "ai-audit",
|
|
809
|
+
"description": "AI models commonly generate code with insecure default configurations: CORS *, disabled SSL verification, permissive CSP, or open CORS origins.",
|
|
810
|
+
"patterns": [
|
|
811
|
+
{ "pattern": "cors\\s*\\(\\s*\\{\\s*origin\\s*:\\s*(?:['\"]?\\*['\"]?|true)", "flags": "gi" },
|
|
812
|
+
{ "pattern": "Access-Control-Allow-Origin['\"]\\s*,\\s*['\"]\\*", "flags": "gi" },
|
|
813
|
+
{ "pattern": "rejectUnauthorized\\s*:\\s*false", "flags": "gi" },
|
|
814
|
+
{ "pattern": "NODE_TLS_REJECT_UNAUTHORIZED\\s*=\\s*['\"]?0['\"]?", "flags": "gi" },
|
|
815
|
+
{ "pattern": "content-security-policy['\"]\\s*,\\s*['\"]default-src\\s+\\*", "flags": "gi" },
|
|
816
|
+
{ "pattern": "sameSite\\s*:\\s*['\"]none['\"]\\s*,?\\s*secure\\s*:\\s*false", "flags": "gi" }
|
|
817
|
+
],
|
|
818
|
+
"fix_suggestion": "Replace wildcard CORS with specific allowed origins. Enable SSL verification. Use restrictive CSP. Set secure cookies.",
|
|
819
|
+
"penalty": "Security misconfiguration",
|
|
820
|
+
"languages": ["typescript", "javascript", "python"],
|
|
821
|
+
"packs": ["ai-audit"],
|
|
822
|
+
"fixability": "flag-only",
|
|
823
|
+
"transform_type": null,
|
|
824
|
+
"scaffold_id": null,
|
|
825
|
+
"guidance_url": null
|
|
826
|
+
},
|
|
827
|
+
{
|
|
828
|
+
"id": "AI-AUDIT-006",
|
|
829
|
+
"name": "Unresolved Compliance TODOs",
|
|
830
|
+
"severity": "low",
|
|
831
|
+
"confidence": "high",
|
|
832
|
+
"category": "ai-audit",
|
|
833
|
+
"description": "AI-generated code often includes TODO/FIXME comments for compliance-related features (consent, age verification, privacy policy) that may ship unimplemented.",
|
|
834
|
+
"patterns": [
|
|
835
|
+
{ "pattern": "//\\s*(?:TODO|FIXME|HACK|XXX).*(?:consent|age\\s*verif|privacy\\s*policy|parental|coppa|gdpr|data\\s*retention)", "flags": "gi" },
|
|
836
|
+
{ "pattern": "//\\s*(?:TODO|FIXME).*(?:implement|add|need|require).*(?:auth|login|permission|access\\s*control)", "flags": "gi" },
|
|
837
|
+
{ "pattern": "#\\s*(?:TODO|FIXME).*(?:consent|age\\s*verif|privacy|parental|coppa)", "flags": "gi" }
|
|
838
|
+
],
|
|
839
|
+
"fix_suggestion": "Resolve all compliance-related TODOs before shipping. Each unresolved TODO is a potential COPPA violation in production.",
|
|
840
|
+
"penalty": "Unimplemented compliance requirement",
|
|
841
|
+
"languages": ["typescript", "javascript", "python", "java", "swift", "kotlin"],
|
|
842
|
+
"packs": ["ai-audit"],
|
|
843
|
+
"fixability": "flag-only",
|
|
844
|
+
"transform_type": null,
|
|
845
|
+
"scaffold_id": null,
|
|
846
|
+
"guidance_url": null
|
|
847
|
+
},
|
|
848
|
+
{
|
|
849
|
+
"id": "AU-SBD-001",
|
|
850
|
+
"name": "Default Public Profile Visibility",
|
|
851
|
+
"severity": "high",
|
|
852
|
+
"confidence": "low",
|
|
853
|
+
"category": "safety-by-design",
|
|
854
|
+
"description": "User profiles default to public or visible. AU Safety by Design requires privacy-by-default for minors — profiles should be private until explicitly changed by the user or a verified parent.",
|
|
855
|
+
"patterns": [
|
|
856
|
+
{ "pattern": "(?<!(?:mock|Mock|fake|stub|fixture|seed|example|test|Test|expect|assert|//|\\*)\\s{0,20})(?:visibility|profile_?visibility|is_?public|isPublic)\\s*[:=]\\s*(?:['\"]public['\"]|true)", "flags": "gi" },
|
|
857
|
+
{ "pattern": "(?<!(?:mock|Mock|fake|stub|fixture|seed|example|test|Test|expect|assert|//|\\*)\\s{0,20})default(?:_?visibility|_?privacy|_?profile)\\s*[:=]\\s*['\"](?:public|open|visible|everyone)['\"]", "flags": "gi" },
|
|
858
|
+
{ "pattern": "(?<!(?:mock|Mock|fake|stub|fixture|seed|example|test|Test|expect|assert|//|\\*)\\s{0,20})(?:privacy|profilePrivacy)\\s*[:=]\\s*\\{[^}]*default\\s*:\\s*['\"](?:public|open|everyone)['\"]", "flags": "gi" },
|
|
859
|
+
{ "pattern": "(?<!(?:mock|Mock|fake|stub|fixture|seed|example|test|Test|expect|assert|//|\\*)\\s{0,20})(?:showProfile|profileVisible|publicByDefault|show_profile)\\s*[:=]\\s*true", "flags": "gi" },
|
|
860
|
+
{ "pattern": "(?<!(?:mock|Mock|fake|stub|fixture|seed|example|test|Test|expect|assert|admin|Admin|dashboard|internal|//|\\*)\\s{0,20})(?:user|profile|account|member)[^\\n]{0,50}(?:searchable|discoverable|findable)\\s*[:=]\\s*true\\b", "flags": "gi" }
|
|
861
|
+
],
|
|
862
|
+
"fix_suggestion": "Set profile visibility to \"private\" by default. Require explicit user action (or parental consent for children) to make profiles public. AU SbD Principle 1: safety as a fundamental design consideration.",
|
|
863
|
+
"penalty": "Default public exposure of minor profiles",
|
|
864
|
+
"languages": ["typescript", "javascript", "python", "java", "swift", "kotlin", "php", "csharp"],
|
|
865
|
+
"packs": ["au-sbd"],
|
|
866
|
+
"fixability": "flag-only",
|
|
867
|
+
"transform_type": null,
|
|
868
|
+
"scaffold_id": null,
|
|
869
|
+
"guidance_url": null
|
|
870
|
+
},
|
|
871
|
+
{
|
|
872
|
+
"id": "AU-SBD-002",
|
|
873
|
+
"name": "Social Features Without Report/Block",
|
|
874
|
+
"severity": "medium",
|
|
875
|
+
"confidence": "medium",
|
|
876
|
+
"category": "safety-by-design",
|
|
877
|
+
"description": "Social interaction features (comments, posts, messaging) detected without corresponding report or block mechanisms. AU SbD Principle 2 requires users to have tools to protect themselves from harmful interactions. Excludes window.postMessage (IPC) and admin/internal contexts.",
|
|
878
|
+
"patterns": [
|
|
879
|
+
{ "pattern": "(?:addComment|postComment|submitComment|createComment|commentCreate)\\s*(?:=|:|\\()", "flags": "gi" },
|
|
880
|
+
{ "pattern": "(?<!window\\.)(?:sendMessage|createMessage|submitMessage|messageCreate)\\s*(?:=|:|\\()", "flags": "gi" },
|
|
881
|
+
{ "pattern": "(?:createPost|submitPost|publishPost|addPost|postCreate)\\s*(?:=|:|\\()", "flags": "gi" },
|
|
882
|
+
{ "pattern": "(?:addReview|submitReview|createReview|postReview|reviewCreate)\\s*(?:=|:|\\()", "flags": "gi" },
|
|
883
|
+
{ "pattern": "(?:shareContent|createShare|submitShare)\\s*(?:=|:|\\()", "flags": "gi" }
|
|
884
|
+
],
|
|
885
|
+
"fix_suggestion": "Implement report and block mechanisms alongside every social feature. Users must be able to report harmful content and block abusive accounts. AU SbD Principle 2: user empowerment and autonomy.",
|
|
886
|
+
"penalty": "Social features without safety controls",
|
|
887
|
+
"languages": ["typescript", "javascript", "python", "java", "swift", "kotlin", "php"],
|
|
888
|
+
"packs": ["au-sbd"],
|
|
889
|
+
"fixability": "flag-only",
|
|
890
|
+
"transform_type": null,
|
|
891
|
+
"scaffold_id": null,
|
|
892
|
+
"guidance_url": null
|
|
893
|
+
},
|
|
894
|
+
{
|
|
895
|
+
"id": "AU-SBD-003",
|
|
896
|
+
"name": "Unrestricted Direct Messaging for Minors",
|
|
897
|
+
"severity": "critical",
|
|
898
|
+
"confidence": "medium",
|
|
899
|
+
"category": "safety-by-design",
|
|
900
|
+
"description": "Direct messaging or chat functionality without safety controls (contact restrictions, message filtering, or parental oversight). The AU Online Safety Act requires platforms to take reasonable steps to prevent child exploitation in private communications.",
|
|
901
|
+
"patterns": [
|
|
902
|
+
{ "pattern": "(?:directMessage|sendDM|privateMess|createDM|dmChannel|startChat|privateChat|initiateChat)\\s*(?:=|:|\\()", "flags": "gi" },
|
|
903
|
+
{ "pattern": "(?:WebSocket|io\\.connect|socket\\.emit)\\s*\\([^)]*(?:chat|message|dm|private)(?![^\\n]*(?:admin|support|internal|helpdesk|customer_?service))", "flags": "gi" },
|
|
904
|
+
{ "pattern": "(?:allowDMs?|enableDMs?|allow_?direct_?message|enable_?private_?message)\\s*[:=]\\s*true", "flags": "gi" },
|
|
905
|
+
{ "pattern": "(?:contactStranger|messageAnyone|openChat|unrestricted_?message)\\s*[:=]\\s*true", "flags": "gi" }
|
|
906
|
+
],
|
|
907
|
+
"fix_suggestion": "Add safety controls to messaging: restrict contacts to approved friends, implement message filtering, enable parental oversight, and log communications for safety review. AU Online Safety Act 2021 s.45-46.",
|
|
908
|
+
"penalty": "Unrestricted private communication channel",
|
|
909
|
+
"languages": ["typescript", "javascript", "python", "java", "swift", "kotlin"],
|
|
910
|
+
"packs": ["au-sbd"],
|
|
911
|
+
"fixability": "flag-only",
|
|
912
|
+
"transform_type": null,
|
|
913
|
+
"scaffold_id": null,
|
|
914
|
+
"guidance_url": null
|
|
915
|
+
},
|
|
916
|
+
{
|
|
917
|
+
"id": "AU-SBD-004",
|
|
918
|
+
"name": "Recommendation Algorithm Without Safety Guardrails",
|
|
919
|
+
"severity": "high",
|
|
920
|
+
"confidence": "medium",
|
|
921
|
+
"category": "safety-by-design",
|
|
922
|
+
"description": "Content recommendation or feed algorithms detected without safety filtering, content classification, or age-appropriate guardrails. AU SbD requires platforms to assess and mitigate algorithmic harms, particularly for young users.",
|
|
923
|
+
"patterns": [
|
|
924
|
+
{ "pattern": "(?:personalizedFeed|forYouFeed|contentFeed)\\s*(?:=|:|\\()", "flags": "gi" },
|
|
925
|
+
{ "pattern": "(?:algorithm|algo)(?:_?feed|_?rank|_?recommend|_?suggest)\\s*(?:=|:|\\()", "flags": "gi" },
|
|
926
|
+
{ "pattern": "(?:trending|viral|popular)(?:_?content|_?posts|_?feed|_?items)\\s*(?:=|:|\\()(?![^\\n]*(?:curated|editorial|manual|handpick|staff_?pick))", "flags": "gi" },
|
|
927
|
+
{ "pattern": "(?:engagement_?score|clickBait|engagement_?rank|watch_?next|autoplay_?next)\\s*[:=]", "flags": "gi" },
|
|
928
|
+
{ "pattern": "(?:rabbit_?hole|endless_?feed|infinite_?recommend|auto_?suggest)\\s*[:=]\\s*true", "flags": "gi" }
|
|
929
|
+
],
|
|
930
|
+
"fix_suggestion": "Add age-appropriate content filters to recommendation algorithms. Classify content before serving, implement safety guardrails, and provide transparency on how content is selected. AU SbD Principle 3: transparency and accountability.",
|
|
931
|
+
"penalty": "Unfiltered algorithmic content delivery",
|
|
932
|
+
"languages": ["typescript", "javascript", "python", "java", "swift", "kotlin"],
|
|
933
|
+
"packs": ["au-sbd"],
|
|
934
|
+
"fixability": "flag-only",
|
|
935
|
+
"transform_type": null,
|
|
936
|
+
"scaffold_id": null,
|
|
937
|
+
"guidance_url": null
|
|
938
|
+
},
|
|
939
|
+
{
|
|
940
|
+
"id": "AU-SBD-005",
|
|
941
|
+
"name": "Engagement Features Without Time Awareness",
|
|
942
|
+
"severity": "medium",
|
|
943
|
+
"confidence": "medium",
|
|
944
|
+
"category": "safety-by-design",
|
|
945
|
+
"description": "High-engagement features (autoplay, continuous scrolling, notifications) detected without corresponding digital wellbeing controls (screen time limits, break reminders, usage dashboards). AU SbD encourages platforms to build in digital wellbeing tools.",
|
|
946
|
+
"patterns": [
|
|
947
|
+
{ "pattern": "(?:autoPlayNext|playNext|nextEpisode|autoplay_?next)\\s*[:=]\\s*true", "flags": "gi" },
|
|
948
|
+
{ "pattern": "(?:continuous_?play|binge_?mode|marathon_?mode|watch_?party)\\s*[:=]\\s*true", "flags": "gi" },
|
|
949
|
+
{ "pattern": "(?:autoplay|auto_?play)\\s*[:=]\\s*true(?=[^\\n]*(?:feed|playlist|series|queue|channel|episode|next))", "flags": "gi" },
|
|
950
|
+
{ "pattern": "(?:push_?notification|sendNotification|scheduleNotif|notif_?trigger).*(?:re_?engage|comeback|miss_?you|inactive)", "flags": "gi" },
|
|
951
|
+
{ "pattern": "(?:daily_?reward|login_?bonus|daily_?streak|come_?back_?reward)\\s*(?:=|:|\\()", "flags": "gi" }
|
|
952
|
+
],
|
|
953
|
+
"fix_suggestion": "Implement digital wellbeing features: screen time dashboards, break reminders after sustained use, and configurable usage limits (especially for accounts under 18). AU SbD: promote healthy technology use.",
|
|
954
|
+
"penalty": "Engagement-maximizing features without wellbeing controls",
|
|
955
|
+
"languages": ["typescript", "javascript", "python", "java", "swift", "kotlin"],
|
|
956
|
+
"packs": ["au-sbd"],
|
|
957
|
+
"fixability": "flag-only",
|
|
958
|
+
"transform_type": null,
|
|
959
|
+
"scaffold_id": null,
|
|
960
|
+
"guidance_url": null
|
|
961
|
+
},
|
|
962
|
+
{
|
|
963
|
+
"id": "AU-SBD-006",
|
|
964
|
+
"name": "Location Data Without Explicit Consent",
|
|
965
|
+
"severity": "critical",
|
|
966
|
+
"confidence": "low",
|
|
967
|
+
"category": "safety-by-design",
|
|
968
|
+
"description": "Location data collection or sharing enabled without explicit, informed opt-in. AU SbD and the Privacy Act 1988 require data minimization, especially for children's geolocation data — location should never be collected by default.",
|
|
969
|
+
"patterns": [
|
|
970
|
+
{ "pattern": "(?:shareLocation|share_?location|locationSharing|broadcastLocation)\\s*[:=]\\s*true", "flags": "gi" },
|
|
971
|
+
{ "pattern": "(?:location_?visible|show_?location|display_?location|location_?public)\\s*[:=]\\s*true", "flags": "gi" },
|
|
972
|
+
{ "pattern": "(?:trackLocation|location_?tracking|geo_?tracking|locationTracker)\\s*[:=]\\s*true", "flags": "gi" },
|
|
973
|
+
{ "pattern": "navigator\\.geolocation\\.(?:watchPosition|getCurrentPosition)\\s*\\(", "flags": "gi" },
|
|
974
|
+
{ "pattern": "(?:CLLocationManager|LocationManager|FusedLocationProvider).*(?:startUpdating|requestLocation|requestLocationUpdates)", "flags": "gi" }
|
|
975
|
+
],
|
|
976
|
+
"fix_suggestion": "Require explicit opt-in for any location data collection. Never enable location sharing by default. For minors, require parental consent before any geolocation access. AU Privacy Act 1988 APP 3.2.",
|
|
977
|
+
"penalty": "Default location data exposure",
|
|
978
|
+
"languages": ["typescript", "javascript", "python", "java", "swift", "kotlin"],
|
|
979
|
+
"packs": ["au-sbd"],
|
|
980
|
+
"fixability": "flag-only",
|
|
981
|
+
"transform_type": null,
|
|
982
|
+
"scaffold_id": null,
|
|
983
|
+
"guidance_url": null
|
|
984
|
+
},
|
|
985
|
+
{
|
|
986
|
+
"id": "ut-sb142-001",
|
|
987
|
+
"name": "Minor Account Creation Without Age Assurance",
|
|
988
|
+
"severity": "critical",
|
|
989
|
+
"confidence": "medium",
|
|
990
|
+
"category": "age-verification",
|
|
991
|
+
"description": "Utah SB 142 requires an age assurance system with at least 95% accuracy to identify minor account holders (under 18). Account creation flows that lack age verification gates violate this requirement. Excludes test factories and seed scripts.",
|
|
992
|
+
"patterns": [
|
|
993
|
+
{ "pattern": "(?:createUser|signUp|register)\\s*\\((?![^)]*(?:age|dateOfBirth|dob|birthDate|birth_date))[^)]*\\)", "flags": "gi" },
|
|
994
|
+
{ "pattern": "(?:create_user|sign_up|create_account)\\s*\\((?![^)]*(?:age|date_of_birth|dob|birth_date))[^)]*\\)", "flags": "gi" },
|
|
995
|
+
{ "pattern": "(?:RegistrationService)\\.(?:create|register)\\s*\\((?![^)]*(?:age|dob|birth))", "flags": "gi" },
|
|
996
|
+
{ "pattern": "INSERT\\s+INTO\\s+(?:users|accounts)\\s*\\((?![^)]*(?:age|dob|birth_date|date_of_birth))[^)]*\\)\\s*VALUES", "flags": "gi" }
|
|
997
|
+
],
|
|
998
|
+
"fix_suggestion": "Add an age assurance step (date-of-birth collection, age estimation, or ID verification) before account creation. If the user is under 18, flag the account as a minor account and require parental consent before activation. See Utah SB 142 §13-72-201.",
|
|
999
|
+
"penalty": "Up to $2,500 per violation; private right of action for parents",
|
|
1000
|
+
"languages": ["typescript", "javascript", "python", "go", "java", "kotlin", "swift"],
|
|
1001
|
+
"packs": ["ut-sb142"],
|
|
1002
|
+
"fixability": "guided",
|
|
1003
|
+
"transform_type": null,
|
|
1004
|
+
"scaffold_id": "age-gate-auth",
|
|
1005
|
+
"guidance_url": null
|
|
1006
|
+
},
|
|
1007
|
+
{
|
|
1008
|
+
"id": "ut-sb142-002",
|
|
1009
|
+
"name": "Missing Parental Consent for Minor Account",
|
|
1010
|
+
"severity": "critical",
|
|
1011
|
+
"confidence": "low",
|
|
1012
|
+
"category": "parental-consent",
|
|
1013
|
+
"description": "Utah SB 142 requires verifiable parental consent before a minor (under 18) can use a social media platform or download apps. Code that activates minor accounts without a parental consent verification step violates this requirement.",
|
|
1014
|
+
"patterns": [
|
|
1015
|
+
{ "pattern": "(?<!(?:mock|Mock|fake|stub|fixture|test|Test|expect|assert|//|\\*)\\s{0,20})(?:activateAccount|enableAccount|verifyEmail|confirmRegistration)\\s*\\((?![^)]*(?:parent|guardian|consent|parental))[^)]*\\)", "flags": "gi" },
|
|
1016
|
+
{ "pattern": "(?<!(?:mock|Mock|fake|stub|fixture|test|Test|expect|assert|//|\\*)\\s{0,20})(?:activate_account|enable_account|verify_email|confirm_registration)\\s*\\((?![^)]*(?:parent|guardian|consent|parental))[^)]*\\)", "flags": "gi" },
|
|
1017
|
+
{ "pattern": "(?<!(?:mock|Mock|fake|stub|fixture|test|Test|expect|assert|//|\\*)\\s{0,20})(?:activate|enable|register)[^\\n]{0,40}(?:isMinor|is_minor|isUnder18|is_under_18)\\s*(?:&&|\\|\\||and|or)\\s*(?!.*(?:parentConsent|parent_consent|guardianApproval|guardian_approval))", "flags": "gi" },
|
|
1018
|
+
{ "pattern": "(?<!(?:mock|Mock|fake|stub|fixture|seed|example|test|Test|expect|assert|//|\\*)\\s{0,20})(?:minor|child|teen)(?:Account|_account|Profile|_profile)\\s*[:=]\\s*(?:true|1|'active'|\"active\")", "flags": "gi" }
|
|
1019
|
+
],
|
|
1020
|
+
"fix_suggestion": "Before activating any minor account, implement a verifiable parental consent flow: send a verification email/SMS to a parent-linked account, require parental ID verification, or integrate with a COPPA-safe consent provider. See Utah SB 142 §13-72-202.",
|
|
1021
|
+
"penalty": "Up to $2,500 per violation; private right of action for parents",
|
|
1022
|
+
"languages": ["typescript", "javascript", "python", "go", "java", "kotlin", "swift"],
|
|
1023
|
+
"packs": ["ut-sb142"],
|
|
1024
|
+
"fixability": "guided",
|
|
1025
|
+
"transform_type": null,
|
|
1026
|
+
"scaffold_id": null,
|
|
1027
|
+
"guidance_url": null
|
|
1028
|
+
},
|
|
1029
|
+
{
|
|
1030
|
+
"id": "ut-sb142-003",
|
|
1031
|
+
"name": "Default DM Access Open for Minors",
|
|
1032
|
+
"severity": "high",
|
|
1033
|
+
"confidence": "medium",
|
|
1034
|
+
"category": "messaging-safety",
|
|
1035
|
+
"description": "Utah SB 142 requires that direct messaging for minor accounts be restricted to connected accounts only by default. Code that enables open or unrestricted DM access for all users (including minors) violates this requirement.",
|
|
1036
|
+
"patterns": [
|
|
1037
|
+
{ "pattern": "(?:allowDirectMessages|allow_direct_messages|dmEnabled|dm_enabled|messagesEnabled|messages_enabled)\\s*[:=]\\s*(?:true|1|'all'|\"all\"|'everyone'|\"everyone\")", "flags": "gi" },
|
|
1038
|
+
{ "pattern": "(?:messagingPermission|messaging_permission|dmAccess|dm_access|messageAccess|message_access)\\s*[:=]\\s*(?:'public'|\"public\"|'open'|\"open\"|'all'|\"all\")", "flags": "gi" },
|
|
1039
|
+
{ "pattern": "(?:canMessage|can_message|canDM|can_dm)\\s*[:=]\\s*(?:true|1)(?!.*(?:friend|follow|connect|mutual))", "flags": "gi" },
|
|
1040
|
+
{ "pattern": "default(?:_?[Mm]essaging|_?[Dd][Mm])\\s*[:=]\\s*(?:'open'|\"open\"|'public'|\"public\"|true)", "flags": "gi" }
|
|
1041
|
+
],
|
|
1042
|
+
"fix_suggestion": "Set default DM permissions for minor accounts to 'connected-only' or 'friends-only'. Only allow messaging between mutually connected accounts. Provide parental controls to further restrict messaging. See Utah SB 142 §13-72-301.",
|
|
1043
|
+
"penalty": "Up to $2,500 per violation; private right of action for parents",
|
|
1044
|
+
"languages": ["typescript", "javascript", "python", "go", "java", "kotlin", "swift"],
|
|
1045
|
+
"packs": ["ut-sb142"],
|
|
1046
|
+
"fixability": "guided",
|
|
1047
|
+
"transform_type": null,
|
|
1048
|
+
"scaffold_id": null,
|
|
1049
|
+
"guidance_url": null
|
|
1050
|
+
},
|
|
1051
|
+
{
|
|
1052
|
+
"id": "ut-sb142-004",
|
|
1053
|
+
"name": "Missing Parental Supervisory Tools",
|
|
1054
|
+
"severity": "high",
|
|
1055
|
+
"confidence": "medium",
|
|
1056
|
+
"category": "parental-controls",
|
|
1057
|
+
"description": "Utah SB 142 requires platforms to offer parents supervisory tools: time limits, mandatory break scheduling, usage data viewing, connected account lists, and setting-change notifications. Applications that provide user accounts for minors without implementing or referencing a parental dashboard violate this requirement.",
|
|
1058
|
+
"patterns": [
|
|
1059
|
+
{ "pattern": "(?:minor|child|student|teen|kid|youth)\\w*(?:Settings|Config|Account|Profile|Preferences)\\s*[:=]\\s*\\{(?![^}]*(?:parent|guardian|supervisory|parental|family))[^}]*\\}", "flags": "gi" },
|
|
1060
|
+
{ "pattern": "(?:screenTime|screen_time|timeLimit|time_limit|usageLimit|usage_limit)\\s*[:=]\\s*(?:null|undefined|false|0|'disabled'|\"disabled\")", "flags": "gi" },
|
|
1061
|
+
{ "pattern": "(?:parentalControls|parental_controls|familySettings|family_settings)\\s*[:=]\\s*(?:false|null|undefined|'disabled'|\"disabled\")", "flags": "gi" }
|
|
1062
|
+
],
|
|
1063
|
+
"fix_suggestion": "Implement a parental supervisory dashboard that allows parents to: set daily time limits, schedule mandatory breaks, view usage data and connected account lists, and receive notifications when account settings change. See Utah SB 142 §13-72-302.",
|
|
1064
|
+
"penalty": "Up to $2,500 per violation; private right of action for parents",
|
|
1065
|
+
"languages": ["typescript", "javascript", "python", "go", "java", "kotlin", "swift"],
|
|
1066
|
+
"packs": ["ut-sb142"],
|
|
1067
|
+
"fixability": "flag-only",
|
|
1068
|
+
"transform_type": null,
|
|
1069
|
+
"scaffold_id": null,
|
|
1070
|
+
"guidance_url": null
|
|
1071
|
+
},
|
|
1072
|
+
{
|
|
1073
|
+
"id": "ut-sb142-005",
|
|
1074
|
+
"name": "Minor Profile Visible to Search Engines",
|
|
1075
|
+
"severity": "medium",
|
|
1076
|
+
"confidence": "medium",
|
|
1077
|
+
"category": "privacy-defaults",
|
|
1078
|
+
"description": "Utah SB 142 requires that minor accounts have search engine indexing disabled by default and account visibility restricted to connected users only. Code that allows public profile indexing or unrestricted profile visibility for all users violates this requirement.",
|
|
1079
|
+
"patterns": [
|
|
1080
|
+
{ "pattern": "(?<!(?:mock|Mock|fake|stub|fixture|seed|example|test|Test|expect|assert|admin|Admin|internal|//|\\*)\\s{0,20})(?:user|profile|account|member)[^\\n]{0,50}(?:indexable|seo_?visible|allow_?indexing|search_?engine_?visible)\\s*[:=]\\s*(?:true|1|'yes'|\"yes\")", "flags": "gi" },
|
|
1081
|
+
{ "pattern": "(?:user|profile|account|member|minor|child|student)[^\\n]{0,30}<meta\\s+name=['\"]robots['\"]\\s+content=['\"](?:index|all)['\"]", "flags": "gi" },
|
|
1082
|
+
{ "pattern": "(?<!(?:mock|Mock|fake|stub|fixture|seed|example|test|Test|expect|assert|//|\\*)\\s{0,20})(?:profileVisibility|profile_visibility|accountVisibility|account_visibility)\\s*[:=]\\s*(?:'public'|\"public\"|'everyone'|\"everyone\"|'all'|\"all\")", "flags": "gi" },
|
|
1083
|
+
{ "pattern": "(?<!(?:mock|Mock|fake|stub|fixture|seed|example|test|Test|expect|assert|//|\\*)\\s{0,20})(?:isPublicProfile|is_public_profile|publicProfile|public_profile)\\s*[:=]\\s*(?:true|1)", "flags": "gi" },
|
|
1084
|
+
{ "pattern": "(?<!(?:mock|Mock|fake|stub|fixture|seed|example|test|Test|//|\\*)\\s{0,20})X-Robots-Tag\\s*[:=]\\s*(?:'index'|\"index\"|'all'|\"all\")", "flags": "gi" }
|
|
1085
|
+
],
|
|
1086
|
+
"fix_suggestion": "Default minor accounts to non-indexable (noindex, nofollow) and restrict profile visibility to connected/approved users only. Add a robots meta tag or X-Robots-Tag header that blocks search engine crawling for minor profiles. See Utah SB 142 §13-72-301.",
|
|
1087
|
+
"penalty": "Up to $2,500 per violation; private right of action for parents",
|
|
1088
|
+
"languages": ["typescript", "javascript", "python", "go", "java", "kotlin", "swift"],
|
|
1089
|
+
"packs": ["ut-sb142"],
|
|
1090
|
+
"fixability": "guided",
|
|
1091
|
+
"transform_type": null,
|
|
1092
|
+
"scaffold_id": null,
|
|
1093
|
+
"guidance_url": null
|
|
1094
|
+
},
|
|
1095
|
+
{
|
|
1096
|
+
"id": "coppa-2-021",
|
|
1097
|
+
"name": "Biometric Identifier Collection Without VPC",
|
|
1098
|
+
"severity": "critical",
|
|
1099
|
+
"confidence": "medium",
|
|
1100
|
+
"category": "bio",
|
|
1101
|
+
"description": "COPPA 2.0 expands 'personal information' to include biometric identifiers: fingerprints, voiceprints, facial geometry, gait patterns. Collection requires Verifiable Parental Consent (VPC) before any data capture.",
|
|
1102
|
+
"patterns": [
|
|
1103
|
+
{ "pattern": "(?:fingerprint|faceprint|voiceprint|gaitAnalysis|gait_analysis)\\s*[:=]", "flags": "gi" },
|
|
1104
|
+
{ "pattern": "(?:biometric|Biometric)(?:Data|Info|Template|Hash|Feature|Scan)\\s*[:=]", "flags": "gi" },
|
|
1105
|
+
{ "pattern": "(?:faceGeometry|face_geometry|facialGeometry|facial_geometry)\\s*[:=]", "flags": "gi" },
|
|
1106
|
+
{ "pattern": "(?:ARFaceAnchor|ARFaceGeometry)\\.(?:geometry|blendShapes)", "flags": "g" },
|
|
1107
|
+
{ "pattern": "(?:SpeakerRecognition|VoiceEnrollment|VoiceVerification)\\s*\\(", "flags": "g" },
|
|
1108
|
+
{ "pattern": "(?:palmPrint|palm_print|irisPattern|iris_pattern|retinaScan|retina_scan)\\s*[:=]", "flags": "gi" }
|
|
1109
|
+
],
|
|
1110
|
+
"fix_suggestion": "Obtain Verifiable Parental Consent (VPC) before collecting any biometric identifiers. Under COPPA 2.0, biometric data is 'personal information' requiring the highest consent standard. Keep biometric processing local-only where possible.",
|
|
1111
|
+
"penalty": "$51,744 per violation (FTC Final Rule effective April 22, 2026)",
|
|
1112
|
+
"languages": ["typescript", "javascript", "python", "go", "java", "kotlin", "swift"],
|
|
1113
|
+
"packs": ["coppa"],
|
|
1114
|
+
"fixability": "guided",
|
|
1115
|
+
"transform_type": null,
|
|
1116
|
+
"scaffold_id": null,
|
|
1117
|
+
"guidance_url": null
|
|
1118
|
+
},
|
|
1119
|
+
{
|
|
1120
|
+
"id": "coppa-2-022",
|
|
1121
|
+
"name": "Push Notification Token Without Parental Opt-In",
|
|
1122
|
+
"severity": "high",
|
|
1123
|
+
"confidence": "medium",
|
|
1124
|
+
"category": "notif",
|
|
1125
|
+
"description": "COPPA 2.0 classifies device push notification tokens as 'online contact information'. Subscribing a child's device to push notifications requires prior parental consent and an opt-out mechanism.",
|
|
1126
|
+
"patterns": [
|
|
1127
|
+
{ "pattern": "(?:messaging|Messaging)\\.(?:getToken|requestPermission|subscribeToTopic)\\s*\\(", "flags": "g" },
|
|
1128
|
+
{ "pattern": "(?:registerForRemoteNotifications|requestAuthorization)\\s*\\(\\s*\\[?\\s*\\.(?:alert|badge|sound)", "flags": "g" },
|
|
1129
|
+
{ "pattern": "(?:PushNotificationIOS|PushNotification)\\.(?:requestPermissions|configure)\\s*\\(", "flags": "g" },
|
|
1130
|
+
{ "pattern": "(?:expo-notifications|@notifee|react-native-push-notification).*(?:requestPermissions|getToken)", "flags": "gi" },
|
|
1131
|
+
{ "pattern": "(?:saveDeviceToken|storeDeviceToken|registerDeviceToken|savePushToken|storePushToken)\\s*\\(", "flags": "gi" }
|
|
1132
|
+
],
|
|
1133
|
+
"fix_suggestion": "Gate push notification token registration behind a parental consent check. Under COPPA 2.0, push tokens are 'online contact information' — parents must explicitly opt in, and you must provide an opt-out mechanism accessible from a parental dashboard.",
|
|
1134
|
+
"penalty": "$51,744 per violation (FTC Final Rule effective April 22, 2026)",
|
|
1135
|
+
"languages": ["typescript", "javascript", "swift", "kotlin", "java"],
|
|
1136
|
+
"packs": ["coppa"],
|
|
1137
|
+
"fixability": "guided",
|
|
1138
|
+
"transform_type": null,
|
|
1139
|
+
"scaffold_id": null,
|
|
1140
|
+
"guidance_url": null
|
|
1141
|
+
},
|
|
1142
|
+
{
|
|
1143
|
+
"id": "coppa-2-023",
|
|
1144
|
+
"name": "Ed-Tech Data Use Beyond Educational Purpose",
|
|
1145
|
+
"severity": "high",
|
|
1146
|
+
"confidence": "low",
|
|
1147
|
+
"category": "edu",
|
|
1148
|
+
"description": "COPPA 2.0 restricts ed-tech providers operating under the 'school official' exception: student data may only be used for the educational purpose authorized by the school. No advertising, profiling, or secondary data use.",
|
|
1149
|
+
"patterns": [
|
|
1150
|
+
{ "pattern": "(?:student|Student)(?:Data|Profile|Record|Info).*(?:marketing|advertising|adTargeting|ad_targeting|profiling|analytics\\.identify|recommend)", "flags": "gi" },
|
|
1151
|
+
{ "pattern": "(?:classroomData|classroom_data|schoolData|school_data).*(?:thirdParty|third_party|partner|advertis|market)", "flags": "gi" },
|
|
1152
|
+
{ "pattern": "(?:edtech|EdTech|LMS|lms).*(?:analytics\\.track|mixpanel|amplitude|segment\\.identify)", "flags": "gi" },
|
|
1153
|
+
{ "pattern": "(?:shareStudentData|share_student_data|exportStudentRecords|export_student_records)\\s*\\(", "flags": "gi" }
|
|
1154
|
+
],
|
|
1155
|
+
"fix_suggestion": "Ensure ed-tech data collected under the 'school official' exception is used exclusively for the authorized educational purpose. Remove any analytics, advertising, or profiling code paths that touch student data. COPPA 2.0 makes this an explicit prohibition.",
|
|
1156
|
+
"penalty": "$51,744 per violation (FTC Final Rule effective April 22, 2026)",
|
|
1157
|
+
"languages": ["typescript", "javascript", "python", "go", "java", "kotlin"],
|
|
1158
|
+
"packs": ["coppa"],
|
|
1159
|
+
"fixability": "guided",
|
|
1160
|
+
"transform_type": null,
|
|
1161
|
+
"scaffold_id": null,
|
|
1162
|
+
"guidance_url": null
|
|
1163
|
+
},
|
|
1164
|
+
{
|
|
1165
|
+
"id": "coppa-2-024",
|
|
1166
|
+
"name": "Data Retention Beyond Reasonable Necessity",
|
|
1167
|
+
"severity": "medium",
|
|
1168
|
+
"confidence": "low",
|
|
1169
|
+
"category": "retention",
|
|
1170
|
+
"description": "COPPA 2.0 strengthens data retention requirements: operators must delete children's personal information when it is no longer reasonably necessary for the purpose for which it was collected. Indefinite retention or missing deletion mechanisms violate this requirement.",
|
|
1171
|
+
"patterns": [
|
|
1172
|
+
{ "pattern": "(?:retentionPolicy|retention_policy|dataRetention|data_retention)\\s*[:=]\\s*(?:'forever'|\"forever\"|'indefinite'|\"indefinite\"|'none'|\"none\"|null|undefined|-1|0)", "flags": "gi" },
|
|
1173
|
+
{ "pattern": "(?:deleteAfterDays|delete_after_days|ttlDays|ttl_days|expiresIn|expires_in)\\s*[:=]\\s*(?:null|undefined|0|-1|false)", "flags": "gi" },
|
|
1174
|
+
{ "pattern": "(?:neverDelete|never_delete|keepForever|keep_forever|permanentStorage|permanent_storage)\\s*[:=]\\s*true", "flags": "gi" },
|
|
1175
|
+
{ "pattern": "(?:childData|child_data|minorData|minor_data|studentData|student_data).*(?:archive|Archive|longTermStorage|long_term_storage)", "flags": "gi" }
|
|
1176
|
+
],
|
|
1177
|
+
"fix_suggestion": "Implement automatic data deletion policies for children's personal information. Set reasonable TTLs based on the purpose of collection. Add a scheduled deletion job that purges expired child data. COPPA 2.0 requires deletion when data is no longer reasonably necessary.",
|
|
1178
|
+
"penalty": "$51,744 per violation (FTC Final Rule effective April 22, 2026)",
|
|
1179
|
+
"languages": ["typescript", "javascript", "python", "go", "java", "kotlin"],
|
|
1180
|
+
"packs": ["coppa"],
|
|
1181
|
+
"fixability": "guided",
|
|
1182
|
+
"transform_type": null,
|
|
1183
|
+
"scaffold_id": null,
|
|
1184
|
+
"guidance_url": null
|
|
1185
|
+
},
|
|
1186
|
+
{
|
|
1187
|
+
"id": "coppa-2-025",
|
|
1188
|
+
"name": "Consent Mechanism Not Meeting VPC Standard",
|
|
1189
|
+
"severity": "high",
|
|
1190
|
+
"confidence": "low",
|
|
1191
|
+
"category": "consent",
|
|
1192
|
+
"description": "COPPA 2.0 requires Verifiable Parental Consent (VPC) via methods that provide a greater level of assurance: signed consent forms, credit card transactions, video calls, government ID, or knowledge-based authentication. Simple email-based consent ('email plus') is only valid for internal use.",
|
|
1193
|
+
"patterns": [
|
|
1194
|
+
{ "pattern": "(?:parentConsent|parent_consent|parentalConsent|parental_consent)\\s*[:=]\\s*(?:true|1|'yes'|\"yes\")", "flags": "gi" },
|
|
1195
|
+
{ "pattern": "(?:consentMethod|consent_method|verificationMethod|verification_method)\\s*[:=]\\s*(?:'email'|\"email\"|'checkbox'|\"checkbox\"|'click'|\"click\")", "flags": "gi" },
|
|
1196
|
+
{ "pattern": "(?:parentEmail|parent_email).*(?:sendVerification|send_verification|sendConsent|send_consent)\\s*\\(", "flags": "gi" },
|
|
1197
|
+
{ "pattern": "<input[^>]*type=['\"]checkbox['\"][^>]*(?:consent|agree|parent)", "flags": "gi" }
|
|
1198
|
+
],
|
|
1199
|
+
"fix_suggestion": "Upgrade consent mechanism to meet COPPA 2.0 VPC standards. For external data sharing, use credit card verification, video calls, government ID, or knowledge-based authentication. Simple checkboxes and email confirmations do not meet the VPC standard for external use of children's data.",
|
|
1200
|
+
"penalty": "$51,744 per violation (FTC Final Rule effective April 22, 2026)",
|
|
1201
|
+
"languages": ["typescript", "javascript", "python", "go", "java", "kotlin", "swift"],
|
|
1202
|
+
"packs": ["coppa"],
|
|
1203
|
+
"fixability": "guided",
|
|
1204
|
+
"transform_type": null,
|
|
1205
|
+
"scaffold_id": null,
|
|
1206
|
+
"guidance_url": null
|
|
1207
|
+
},
|
|
1208
|
+
|
|
1209
|
+
{
|
|
1210
|
+
"id": "aadc-defaults-001",
|
|
1211
|
+
"name": "Default Privacy Set to Public",
|
|
1212
|
+
"severity": "critical",
|
|
1213
|
+
"confidence": "high",
|
|
1214
|
+
"category": "privacy",
|
|
1215
|
+
"description": "AADC Standard 7 requires settings to be 'high privacy' by default. Children's data should only be visible to others if the child actively changes the setting. Default-public profiles, content, or activity violate this standard.",
|
|
1216
|
+
"patterns": [
|
|
1217
|
+
{ "pattern": "(?:default|initial)(?:Privacy|Visibility|Setting)\\s*[:=]\\s*['\"]?(?:public|open|everyone|all)['\"]?", "flags": "gi" },
|
|
1218
|
+
{ "pattern": "shareByDefault\\s*[:=]\\s*true", "flags": "gi" },
|
|
1219
|
+
{ "pattern": "(?:discoverability|discoverable)\\s*[:=]\\s*['\"]?(?:public|everyone|all)['\"]?", "flags": "gi" },
|
|
1220
|
+
{ "pattern": "(?:searchable|allowStrangers|showOnlineStatus|showActivity)\\s*[:=]\\s*true", "flags": "gi" }
|
|
1221
|
+
],
|
|
1222
|
+
"fix_suggestion": "Set all privacy defaults to the most restrictive option. Profiles, activity, and content should be private by default. Users (especially children) should actively opt in to share data with others. See ICO AADC Standard 7.",
|
|
1223
|
+
"penalty": "Up to £17.5 million or 4% of annual global turnover (UK GDPR)",
|
|
1224
|
+
"languages": ["typescript", "javascript", "python", "go", "java", "kotlin", "swift"],
|
|
1225
|
+
"packs": ["uk-aadc"],
|
|
1226
|
+
"fixability": "auto",
|
|
1227
|
+
"transform_type": null,
|
|
1228
|
+
"scaffold_id": null,
|
|
1229
|
+
"guidance_url": "https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/childrens-information/childrens-code-guidance-and-resources/age-appropriate-design-a-code-of-practice-for-online-services/7-default-settings/"
|
|
1230
|
+
},
|
|
1231
|
+
{
|
|
1232
|
+
"id": "aadc-defaults-002",
|
|
1233
|
+
"name": "Opt-Out Tracking Enabled by Default",
|
|
1234
|
+
"severity": "high",
|
|
1235
|
+
"confidence": "high",
|
|
1236
|
+
"category": "tracking",
|
|
1237
|
+
"description": "AADC Standard 7 requires optional data uses to be individually selected and activated. Tracking, analytics, or personalization enabled by default with an opt-out mechanism violates this standard.",
|
|
1238
|
+
"patterns": [
|
|
1239
|
+
{ "pattern": "(?:tracking|analytics|personalization|marketing)(?:Enabled|Active|On)\\s*[:=]\\s*true", "flags": "gi" },
|
|
1240
|
+
{ "pattern": "defaultConsent\\s*[:=]\\s*(?:true|['\"]granted['\"]|['\"]accepted['\"])", "flags": "gi" },
|
|
1241
|
+
{ "pattern": "optOut|opt_out|optedOut", "flags": "gi" }
|
|
1242
|
+
],
|
|
1243
|
+
"fix_suggestion": "Switch from opt-out to opt-in for all tracking, analytics, and personalization. These features must be off by default and require active user consent before activation. See ICO AADC Standard 7.",
|
|
1244
|
+
"penalty": "Up to £17.5 million or 4% of annual global turnover (UK GDPR)",
|
|
1245
|
+
"languages": ["typescript", "javascript", "python", "go", "java", "kotlin", "swift", "html"],
|
|
1246
|
+
"packs": ["uk-aadc"],
|
|
1247
|
+
"fixability": "guided",
|
|
1248
|
+
"transform_type": null,
|
|
1249
|
+
"scaffold_id": null,
|
|
1250
|
+
"guidance_url": "https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/childrens-information/childrens-code-guidance-and-resources/age-appropriate-design-a-code-of-practice-for-online-services/7-default-settings/"
|
|
1251
|
+
},
|
|
1252
|
+
{
|
|
1253
|
+
"id": "aadc-minimisation-003",
|
|
1254
|
+
"name": "Excessive Personal Data Collection",
|
|
1255
|
+
"severity": "high",
|
|
1256
|
+
"confidence": "medium",
|
|
1257
|
+
"category": "data-collection",
|
|
1258
|
+
"description": "AADC Standard 8 requires collecting only the minimum personal data needed to provide the service. Requiring fields like phone, address, school, gender, or ethnicity beyond what is necessary violates data minimisation.",
|
|
1259
|
+
"patterns": [
|
|
1260
|
+
{ "pattern": "(?:required|mandatory)\\s*[:=].*(?:phone|address|school|gender|ethnicity|religion)", "flags": "gi" },
|
|
1261
|
+
{ "pattern": "<input[^>]*required[^>]*(?:phone|address|middleName|employer|school)", "flags": "gi" },
|
|
1262
|
+
{ "pattern": "(?:collectAll|gatherAll|harvestData)", "flags": "gi" }
|
|
1263
|
+
],
|
|
1264
|
+
"fix_suggestion": "Review which personal data fields are truly required for your service. Make non-essential fields optional. Give children choices over which elements of data they wish to provide. See ICO AADC Standard 8.",
|
|
1265
|
+
"penalty": "Up to £17.5 million or 4% of annual global turnover (UK GDPR)",
|
|
1266
|
+
"languages": ["typescript", "javascript", "python", "html", "php"],
|
|
1267
|
+
"packs": ["uk-aadc"],
|
|
1268
|
+
"fixability": "guided",
|
|
1269
|
+
"transform_type": null,
|
|
1270
|
+
"scaffold_id": null,
|
|
1271
|
+
"guidance_url": "https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/childrens-information/childrens-code-guidance-and-resources/age-appropriate-design-a-code-of-practice-for-online-services/8-data-minimisation/"
|
|
1272
|
+
},
|
|
1273
|
+
{
|
|
1274
|
+
"id": "aadc-sharing-004",
|
|
1275
|
+
"name": "Third-Party Data Sharing Without Child Safety Check",
|
|
1276
|
+
"severity": "critical",
|
|
1277
|
+
"confidence": "medium",
|
|
1278
|
+
"category": "data-sharing",
|
|
1279
|
+
"description": "AADC Standard 9 prohibits disclosing children's data unless there is a compelling reason. Analytics and advertising SDKs that share data with third parties require child-safety checks before initialization.",
|
|
1280
|
+
"patterns": [
|
|
1281
|
+
{ "pattern": "(?:facebook|google|amplitude|mixpanel|segment)\\.(?:track|identify|log|init)", "flags": "gi" },
|
|
1282
|
+
{ "pattern": "(?:AdMob|MoPub|UnityAds|IronSource|AppLovin|InMobi)", "flags": "g" },
|
|
1283
|
+
{ "pattern": "(?:ad|advertising)SDK\\.init", "flags": "gi" },
|
|
1284
|
+
{ "pattern": "(?:databroker|dataBroker|sellData|dataMarketplace)", "flags": "gi" }
|
|
1285
|
+
],
|
|
1286
|
+
"fix_suggestion": "Before initializing third-party SDKs, check user age and disable data sharing for children. Use child-directed SDK configurations (e.g., tag_for_child_directed_treatment). Do not share children's data with data brokers or ad networks. See ICO AADC Standard 9.",
|
|
1287
|
+
"penalty": "Up to £17.5 million or 4% of annual global turnover (UK GDPR)",
|
|
1288
|
+
"languages": ["typescript", "javascript", "python", "java", "kotlin", "swift"],
|
|
1289
|
+
"packs": ["uk-aadc"],
|
|
1290
|
+
"fixability": "guided",
|
|
1291
|
+
"transform_type": null,
|
|
1292
|
+
"scaffold_id": null,
|
|
1293
|
+
"guidance_url": "https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/childrens-information/childrens-code-guidance-and-resources/age-appropriate-design-a-code-of-practice-for-online-services/9-data-sharing/"
|
|
1294
|
+
},
|
|
1295
|
+
{
|
|
1296
|
+
"id": "aadc-geolocation-005",
|
|
1297
|
+
"name": "Geolocation Enabled by Default",
|
|
1298
|
+
"severity": "critical",
|
|
1299
|
+
"confidence": "high",
|
|
1300
|
+
"category": "geolocation",
|
|
1301
|
+
"description": "AADC Standard 10 requires geolocation options to be switched off by default. Location tracking, sharing, and high-accuracy positioning must not be activated without explicit user action.",
|
|
1302
|
+
"patterns": [
|
|
1303
|
+
{ "pattern": "(?:geolocation|location(?:Tracking|Sharing|Service))(?:Enabled|Active|On|Default)\\s*[:=]\\s*true", "flags": "gi" },
|
|
1304
|
+
{ "pattern": "(?:enableLocation|shareLocation|trackLocation)\\s*[:=]\\s*true", "flags": "gi" },
|
|
1305
|
+
{ "pattern": "(?:enableHighAccuracy|highAccuracy)\\s*[:=]\\s*true", "flags": "gi" }
|
|
1306
|
+
],
|
|
1307
|
+
"fix_suggestion": "Set geolocation to off by default. Require explicit user action to enable location services. When location is active, provide a prominent visible indicator. Location sharing with others should reset to off at end of session. See ICO AADC Standard 10.",
|
|
1308
|
+
"penalty": "Up to £17.5 million or 4% of annual global turnover (UK GDPR)",
|
|
1309
|
+
"languages": ["typescript", "javascript", "python", "java", "kotlin", "swift"],
|
|
1310
|
+
"packs": ["uk-aadc"],
|
|
1311
|
+
"fixability": "auto",
|
|
1312
|
+
"transform_type": null,
|
|
1313
|
+
"scaffold_id": null,
|
|
1314
|
+
"guidance_url": "https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/childrens-information/childrens-code-guidance-and-resources/age-appropriate-design-a-code-of-practice-for-online-services/10-geolocation/"
|
|
1315
|
+
},
|
|
1316
|
+
{
|
|
1317
|
+
"id": "aadc-geolocation-006",
|
|
1318
|
+
"name": "Continuous Background Location Tracking",
|
|
1319
|
+
"severity": "high",
|
|
1320
|
+
"confidence": "high",
|
|
1321
|
+
"category": "geolocation",
|
|
1322
|
+
"description": "AADC Standard 10 requires using minimum granularity for geolocation. Continuous background location tracking or watch-based location monitoring collects excessive positional data from children.",
|
|
1323
|
+
"patterns": [
|
|
1324
|
+
{ "pattern": "(?:backgroundLocation|Background.*Location.*Mode|backgroundLocationUpdate)", "flags": "gi" },
|
|
1325
|
+
{ "pattern": "startUpdatingLocation|requestLocationUpdates|LocationManager.*startMonitoring", "flags": "g" },
|
|
1326
|
+
{ "pattern": "navigator\\.geolocation\\.watchPosition", "flags": "g" }
|
|
1327
|
+
],
|
|
1328
|
+
"fix_suggestion": "Use single-point location requests instead of continuous monitoring. Avoid background location tracking. Use the minimum granularity needed (e.g., city-level rather than precise coordinates). See ICO AADC Standard 10.",
|
|
1329
|
+
"penalty": "Up to £17.5 million or 4% of annual global turnover (UK GDPR)",
|
|
1330
|
+
"languages": ["typescript", "javascript", "java", "kotlin", "swift"],
|
|
1331
|
+
"packs": ["uk-aadc"],
|
|
1332
|
+
"fixability": "guided",
|
|
1333
|
+
"transform_type": null,
|
|
1334
|
+
"scaffold_id": null,
|
|
1335
|
+
"guidance_url": "https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/childrens-information/childrens-code-guidance-and-resources/age-appropriate-design-a-code-of-practice-for-online-services/10-geolocation/"
|
|
1336
|
+
},
|
|
1337
|
+
{
|
|
1338
|
+
"id": "aadc-profiling-007",
|
|
1339
|
+
"name": "Profiling or Algorithmic Feed Enabled by Default",
|
|
1340
|
+
"severity": "critical",
|
|
1341
|
+
"confidence": "high",
|
|
1342
|
+
"category": "profiling",
|
|
1343
|
+
"description": "AADC Standard 12 requires profiling to be switched off by default for children. Algorithmic content feeds, behavioral profiling, and personalization engines must not be active without explicit opt-in.",
|
|
1344
|
+
"patterns": [
|
|
1345
|
+
{ "pattern": "(?:profiling|personaliz(?:e|ation)|algorithmicFeed)(?:Enabled|Active|On|Default)\\s*[:=]\\s*true", "flags": "gi" },
|
|
1346
|
+
{ "pattern": "(?:enableProfiling|enablePersonalization)\\s*[:=]\\s*true", "flags": "gi" },
|
|
1347
|
+
{ "pattern": "(?:behaviorProfile|userProfile|interestGraph)\\s*[:=]", "flags": "gi" },
|
|
1348
|
+
{ "pattern": "(?:userSegment|audienceSegment|cohort)\\s*[:=]", "flags": "gi" }
|
|
1349
|
+
],
|
|
1350
|
+
"fix_suggestion": "Switch profiling off by default. Provide a chronological or non-personalized feed as the default experience. Only enable algorithmic personalization if the child actively opts in. See ICO AADC Standard 12.",
|
|
1351
|
+
"penalty": "Up to £17.5 million or 4% of annual global turnover (UK GDPR)",
|
|
1352
|
+
"languages": ["typescript", "javascript", "python", "java", "kotlin", "swift"],
|
|
1353
|
+
"packs": ["uk-aadc"],
|
|
1354
|
+
"fixability": "guided",
|
|
1355
|
+
"transform_type": null,
|
|
1356
|
+
"scaffold_id": null,
|
|
1357
|
+
"guidance_url": "https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/childrens-information/childrens-code-guidance-and-resources/age-appropriate-design-a-code-of-practice-for-online-services/12-profiling/"
|
|
1358
|
+
},
|
|
1359
|
+
{
|
|
1360
|
+
"id": "aadc-profiling-008",
|
|
1361
|
+
"name": "Behavioral Data Collection for Recommendation Engine",
|
|
1362
|
+
"severity": "high",
|
|
1363
|
+
"confidence": "medium",
|
|
1364
|
+
"category": "profiling",
|
|
1365
|
+
"description": "AADC Standard 12 restricts profiling children. Collecting behavioral data (interests, habits, browsing patterns) to feed recommendation algorithms requires safeguards to protect children from harmful content amplification.",
|
|
1366
|
+
"patterns": [
|
|
1367
|
+
{ "pattern": "(?:trackBehavior|behavioralData|browsingHistory|viewHistory|watchHistory)", "flags": "gi" },
|
|
1368
|
+
{ "pattern": "(?:recommend|suggest).*(?:algorithm|engine|model|ml)", "flags": "gi" },
|
|
1369
|
+
{ "pattern": "(?:contentRecommend|personalizedFeed|forYou|fyp)", "flags": "gi" }
|
|
1370
|
+
],
|
|
1371
|
+
"fix_suggestion": "If using recommendation algorithms, implement age-appropriate content filtering. Do not amplify harmful, addictive, or age-inappropriate content to children. Provide transparency about why content is recommended. See ICO AADC Standard 12.",
|
|
1372
|
+
"penalty": "Up to £17.5 million or 4% of annual global turnover (UK GDPR)",
|
|
1373
|
+
"languages": ["typescript", "javascript", "python", "java", "kotlin", "swift"],
|
|
1374
|
+
"packs": ["uk-aadc"],
|
|
1375
|
+
"fixability": "guided",
|
|
1376
|
+
"transform_type": null,
|
|
1377
|
+
"scaffold_id": null,
|
|
1378
|
+
"guidance_url": "https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/childrens-information/childrens-code-guidance-and-resources/age-appropriate-design-a-code-of-practice-for-online-services/12-profiling/"
|
|
1379
|
+
},
|
|
1380
|
+
{
|
|
1381
|
+
"id": "aadc-nudge-009",
|
|
1382
|
+
"name": "Pre-Checked Consent or Privacy Boxes",
|
|
1383
|
+
"severity": "high",
|
|
1384
|
+
"confidence": "high",
|
|
1385
|
+
"category": "dark-patterns",
|
|
1386
|
+
"description": "AADC Standard 13 prohibits nudge techniques that lead children to weaken or turn off privacy protections. Pre-checked consent, marketing, or data-sharing boxes are a nudge that defaults to less privacy.",
|
|
1387
|
+
"patterns": [
|
|
1388
|
+
{ "pattern": "(?:checked|defaultChecked|preChecked)\\s*[:=]\\s*true.*(?:consent|share|track|market|newsletter|terms)", "flags": "gi" },
|
|
1389
|
+
{ "pattern": "(?:consent|share|track|market|newsletter|terms).*(?:checked|defaultChecked|preChecked)\\s*[:=]\\s*true", "flags": "gi" },
|
|
1390
|
+
{ "pattern": "<input[^>]*checked[^>]*(?:consent|agree|marketing|newsletter|share)", "flags": "gi" }
|
|
1391
|
+
],
|
|
1392
|
+
"fix_suggestion": "Remove all pre-checked consent and data-sharing boxes. Consent inputs should start unchecked, requiring active selection by the user. This applies to marketing consent, newsletter signups, data sharing agreements, and privacy preferences. See ICO AADC Standard 13.",
|
|
1393
|
+
"penalty": "Up to £17.5 million or 4% of annual global turnover (UK GDPR)",
|
|
1394
|
+
"languages": ["typescript", "javascript", "html", "php", "python"],
|
|
1395
|
+
"packs": ["uk-aadc"],
|
|
1396
|
+
"fixability": "auto",
|
|
1397
|
+
"transform_type": null,
|
|
1398
|
+
"scaffold_id": null,
|
|
1399
|
+
"guidance_url": "https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/childrens-information/childrens-code-guidance-and-resources/age-appropriate-design-a-code-of-practice-for-online-services/13-nudge-techniques/"
|
|
1400
|
+
},
|
|
1401
|
+
{
|
|
1402
|
+
"id": "aadc-nudge-010",
|
|
1403
|
+
"name": "Confirmshaming or Guilt-Based Privacy Nudge",
|
|
1404
|
+
"severity": "high",
|
|
1405
|
+
"confidence": "medium",
|
|
1406
|
+
"category": "dark-patterns",
|
|
1407
|
+
"description": "AADC Standard 13 prohibits exploiting psychological processes to weaken children's privacy. Confirmshaming uses guilt, shame, or fear-of-missing-out language to pressure users into sharing more data or accepting weaker privacy settings.",
|
|
1408
|
+
"patterns": [
|
|
1409
|
+
{ "pattern": "(?:confirmSham|guiltTrip|shameText|shameModal|fomo(?:Text|Message|Modal))", "flags": "gi" },
|
|
1410
|
+
{ "pattern": "(?:are you sure|really want to|miss out|lose access).*(?:privacy|private|restrict|decline)", "flags": "gi" },
|
|
1411
|
+
{ "pattern": "(?:everyone.(?:else\\s)?is|your friends are|left behind|missing out).*(?:share|public|join)", "flags": "gi" }
|
|
1412
|
+
],
|
|
1413
|
+
"fix_suggestion": "Present privacy choices neutrally without emotional manipulation. Avoid language that makes children feel bad for choosing privacy. Do not imply social exclusion or loss for choosing restrictive settings. See ICO AADC Standard 13.",
|
|
1414
|
+
"penalty": "Up to £17.5 million or 4% of annual global turnover (UK GDPR)",
|
|
1415
|
+
"languages": ["typescript", "javascript", "html", "python"],
|
|
1416
|
+
"packs": ["uk-aadc"],
|
|
1417
|
+
"fixability": "guided",
|
|
1418
|
+
"transform_type": null,
|
|
1419
|
+
"scaffold_id": null,
|
|
1420
|
+
"guidance_url": "https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/childrens-information/childrens-code-guidance-and-resources/age-appropriate-design-a-code-of-practice-for-online-services/13-nudge-techniques/"
|
|
1421
|
+
},
|
|
1422
|
+
{
|
|
1423
|
+
"id": "aadc-nudge-011",
|
|
1424
|
+
"name": "Privacy-Weakening Reward Mechanism",
|
|
1425
|
+
"severity": "high",
|
|
1426
|
+
"confidence": "medium",
|
|
1427
|
+
"category": "dark-patterns",
|
|
1428
|
+
"description": "AADC Standard 13 prohibits nudges that lead children to provide unnecessary personal data. Offering rewards, unlocks, or premium features in exchange for sharing more data or making profiles public incentivizes weaker privacy.",
|
|
1429
|
+
"patterns": [
|
|
1430
|
+
{ "pattern": "(?:unlock|bonus|reward|premium|upgrade).*(?:share|public|visible|data|profile)", "flags": "gi" },
|
|
1431
|
+
{ "pattern": "(?:shareMore|goPublic|makeVisible).*(?:unlock|get|earn|reward|access)", "flags": "gi" }
|
|
1432
|
+
],
|
|
1433
|
+
"fix_suggestion": "Do not gate features or rewards behind data sharing or public profile requirements. Core service features should be available regardless of privacy settings. See ICO AADC Standard 13.",
|
|
1434
|
+
"penalty": "Up to £17.5 million or 4% of annual global turnover (UK GDPR)",
|
|
1435
|
+
"languages": ["typescript", "javascript", "python", "java", "kotlin", "swift"],
|
|
1436
|
+
"packs": ["uk-aadc"],
|
|
1437
|
+
"fixability": "guided",
|
|
1438
|
+
"transform_type": null,
|
|
1439
|
+
"scaffold_id": null,
|
|
1440
|
+
"guidance_url": "https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/childrens-information/childrens-code-guidance-and-resources/age-appropriate-design-a-code-of-practice-for-online-services/13-nudge-techniques/"
|
|
1441
|
+
},
|
|
1442
|
+
{
|
|
1443
|
+
"id": "aadc-age-012",
|
|
1444
|
+
"name": "Weak Age Gate Using Self-Declaration Only",
|
|
1445
|
+
"severity": "high",
|
|
1446
|
+
"confidence": "medium",
|
|
1447
|
+
"category": "age-assurance",
|
|
1448
|
+
"description": "AADC Standard 3 requires a risk-based approach to recognizing user age. Simple self-declaration checkboxes or dropdowns ('Are you over 13?') are easily bypassed and provide inadequate age assurance for high-risk services.",
|
|
1449
|
+
"patterns": [
|
|
1450
|
+
{ "pattern": "(?:isOver13|isOver18|isAdult|isMinor)\\s*[:=]\\s*(?:true|false|!?\\w+\\.checked)", "flags": "gi" },
|
|
1451
|
+
{ "pattern": "(?:ageGate|age_gate|ageCheck|age_check).*(?:checkbox|select|dropdown|input)", "flags": "gi" },
|
|
1452
|
+
{ "pattern": "(?:age|birth).*(?:self.?report|self.?declare|self.?certif)", "flags": "gi" }
|
|
1453
|
+
],
|
|
1454
|
+
"fix_suggestion": "Implement a risk-based age assurance approach. For high-risk services, use age estimation technology, identity verification, or neutral age estimation rather than simple self-declaration. If unable to verify age, apply the code's standards to all users. See ICO AADC Standard 3.",
|
|
1455
|
+
"penalty": "Up to £17.5 million or 4% of annual global turnover (UK GDPR)",
|
|
1456
|
+
"languages": ["typescript", "javascript", "python", "java", "kotlin", "swift", "html"],
|
|
1457
|
+
"packs": ["uk-aadc"],
|
|
1458
|
+
"fixability": "guided",
|
|
1459
|
+
"transform_type": null,
|
|
1460
|
+
"scaffold_id": null,
|
|
1461
|
+
"guidance_url": "https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/childrens-information/childrens-code-guidance-and-resources/age-appropriate-design-a-code-of-practice-for-online-services/3-age-appropriate-application/"
|
|
1462
|
+
},
|
|
1463
|
+
{
|
|
1464
|
+
"id": "aadc-detrimental-013",
|
|
1465
|
+
"name": "Targeted Advertising to Minors",
|
|
1466
|
+
"severity": "critical",
|
|
1467
|
+
"confidence": "high",
|
|
1468
|
+
"category": "advertising",
|
|
1469
|
+
"description": "AADC Standard 5 prohibits using children's personal data in ways detrimental to their wellbeing. Targeted advertising using children's behavioral data, profiles, or personal information is a detrimental use under the code.",
|
|
1470
|
+
"patterns": [
|
|
1471
|
+
{ "pattern": "(?:targetedAd|personalized(?:Ad|Advert)|behavioralAd).*(?:child|minor|student|kid|teen)", "flags": "gi" },
|
|
1472
|
+
{ "pattern": "(?:child|minor|student|kid|teen).*(?:adTarget|targetAd|personalized(?:Ad|Advert))", "flags": "gi" },
|
|
1473
|
+
{ "pattern": "(?:childProfile|minorProfile|studentProfile).*(?:ad|marketing|monetize)", "flags": "gi" }
|
|
1474
|
+
],
|
|
1475
|
+
"fix_suggestion": "Do not serve targeted or personalized advertising to children. Use only contextual advertising (based on page content, not user data) if advertising is necessary. See ICO AADC Standard 5.",
|
|
1476
|
+
"penalty": "Up to £17.5 million or 4% of annual global turnover (UK GDPR)",
|
|
1477
|
+
"languages": ["typescript", "javascript", "python", "java", "kotlin", "swift"],
|
|
1478
|
+
"packs": ["uk-aadc"],
|
|
1479
|
+
"fixability": "guided",
|
|
1480
|
+
"transform_type": null,
|
|
1481
|
+
"scaffold_id": null,
|
|
1482
|
+
"guidance_url": "https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/childrens-information/childrens-code-guidance-and-resources/age-appropriate-design-a-code-of-practice-for-online-services/5-detrimental-use-of-data/"
|
|
1483
|
+
},
|
|
1484
|
+
{
|
|
1485
|
+
"id": "aadc-parental-014",
|
|
1486
|
+
"name": "Covert Child Monitoring Without Notification",
|
|
1487
|
+
"severity": "high",
|
|
1488
|
+
"confidence": "high",
|
|
1489
|
+
"category": "parental-controls",
|
|
1490
|
+
"description": "AADC Standard 11 requires that if parental monitoring or tracking features are active, the child must be given an obvious sign. Covert surveillance features that hide monitoring from the child violate this standard.",
|
|
1491
|
+
"patterns": [
|
|
1492
|
+
{ "pattern": "(?:silentTrack|hiddenMonitor|stealthMode|covertMonitor|invisibleTrack)", "flags": "gi" },
|
|
1493
|
+
{ "pattern": "(?:hideTracking|invisible.*monitor|stealth.*(?:parent|track|monitor))", "flags": "gi" },
|
|
1494
|
+
{ "pattern": "(?:parentalMonitor|parentTrack|monitorChild|childTrack|parentalSpy)", "flags": "gi" }
|
|
1495
|
+
],
|
|
1496
|
+
"fix_suggestion": "When parental monitoring or tracking is active, display a clear, prominent indicator visible to the child. Provide age-appropriate explanations of what monitoring is active. Respect the child's growing autonomy. See ICO AADC Standard 11.",
|
|
1497
|
+
"penalty": "Up to £17.5 million or 4% of annual global turnover (UK GDPR)",
|
|
1498
|
+
"languages": ["typescript", "javascript", "python", "java", "kotlin", "swift"],
|
|
1499
|
+
"packs": ["uk-aadc"],
|
|
1500
|
+
"fixability": "guided",
|
|
1501
|
+
"transform_type": null,
|
|
1502
|
+
"scaffold_id": null,
|
|
1503
|
+
"guidance_url": "https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/childrens-information/childrens-code-guidance-and-resources/age-appropriate-design-a-code-of-practice-for-online-services/11-parental-controls/"
|
|
1504
|
+
},
|
|
1505
|
+
{
|
|
1506
|
+
"id": "aadc-tools-015",
|
|
1507
|
+
"name": "User Content Without Report or Block Mechanism",
|
|
1508
|
+
"severity": "medium",
|
|
1509
|
+
"confidence": "medium",
|
|
1510
|
+
"category": "safety",
|
|
1511
|
+
"description": "AADC Standard 15 requires prominent tools to help children report concerns. AADC Standard 6 requires active content moderation. User-generated content (comments, messages, posts) without report, flag, or block mechanisms fails both standards.",
|
|
1512
|
+
"patterns": [
|
|
1513
|
+
{ "pattern": "(?:comment|post|message|chat).*(?:submit|publish|send)(?![\\s\\S]{0,1000}(?:report|flag|block|moderate|filter))", "flags": "gi" },
|
|
1514
|
+
{ "pattern": "(?:directMessage|privateChat|sendMessage|userChat)(?![\\s\\S]{0,500}(?:report|block|moderate|filter))", "flags": "gi" }
|
|
1515
|
+
],
|
|
1516
|
+
"fix_suggestion": "Add prominent report, flag, and block mechanisms alongside all user-generated content features. Implement content moderation for user communications. Provide children with easy ways to report harmful content. See ICO AADC Standards 6 and 15.",
|
|
1517
|
+
"penalty": "Up to £17.5 million or 4% of annual global turnover (UK GDPR)",
|
|
1518
|
+
"languages": ["typescript", "javascript", "python", "java", "kotlin", "swift"],
|
|
1519
|
+
"packs": ["uk-aadc"],
|
|
1520
|
+
"fixability": "guided",
|
|
1521
|
+
"transform_type": null,
|
|
1522
|
+
"scaffold_id": null,
|
|
1523
|
+
"guidance_url": "https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/childrens-information/childrens-code-guidance-and-resources/age-appropriate-design-a-code-of-practice-for-online-services/15-online-tools/"
|
|
1524
|
+
},
|
|
1525
|
+
|
|
1526
|
+
{
|
|
1527
|
+
"id": "dsa-ad-profiling-001",
|
|
1528
|
+
"name": "Profiling-Based Ad Targeting Without Minor Exclusion",
|
|
1529
|
+
"severity": "critical",
|
|
1530
|
+
"confidence": "medium",
|
|
1531
|
+
"category": "advertising",
|
|
1532
|
+
"description": "DSA Article 28(2) strictly prohibits presenting advertisements based on profiling using personal data when the platform is aware with reasonable certainty that the recipient is a minor. This ban cannot be overridden by parental consent.",
|
|
1533
|
+
"patterns": [
|
|
1534
|
+
{ "pattern": "(?:targetAudience|behavioralTarget|interest_based|personalized_ad|profile_target)", "flags": "gi" },
|
|
1535
|
+
{ "pattern": "(?:adPersonalization|ad_personalization|personalized_ads)\\s*[:=]\\s*true", "flags": "gi" },
|
|
1536
|
+
{ "pattern": "(?:targeting|retargeting|remarketing)\\s*[:=].*(?:interest|behavior|engagement|browsing)", "flags": "gi" }
|
|
1537
|
+
],
|
|
1538
|
+
"fix_suggestion": "Before serving ads, check if the user is a minor. If so, disable all profiling-based ad targeting. Only contextual advertising (based on page content, not user data) is permitted for minors under DSA Article 28(2). This restriction cannot be waived by parental consent.",
|
|
1539
|
+
"penalty": "Up to 6% of annual global turnover (DSA Article 52)",
|
|
1540
|
+
"languages": ["typescript", "javascript", "python", "java", "kotlin", "swift"],
|
|
1541
|
+
"packs": ["eu-dsa"],
|
|
1542
|
+
"fixability": "guided",
|
|
1543
|
+
"transform_type": null,
|
|
1544
|
+
"scaffold_id": null,
|
|
1545
|
+
"guidance_url": "https://www.eu-digital-services-act.com/Digital_Services_Act_Article_28.html"
|
|
1546
|
+
},
|
|
1547
|
+
{
|
|
1548
|
+
"id": "dsa-autoplay-002",
|
|
1549
|
+
"name": "Media Autoplay Without Minor-Conditional Default",
|
|
1550
|
+
"severity": "high",
|
|
1551
|
+
"confidence": "high",
|
|
1552
|
+
"category": "addictive-design",
|
|
1553
|
+
"description": "DSA Article 28(1) Guidelines require autoplay of video/audio content to be disabled by default for minor users. Autoplay drives extended engagement and undermines minors' ability to control their usage.",
|
|
1554
|
+
"patterns": [
|
|
1555
|
+
{ "pattern": "autoplay|autoPlay|auto_play", "flags": "gi" },
|
|
1556
|
+
{ "pattern": "\\.play\\(\\)", "flags": "g" },
|
|
1557
|
+
{ "pattern": "(?:autoplay|autoPlay|auto_play)\\s*[:=]\\s*true", "flags": "gi" }
|
|
1558
|
+
],
|
|
1559
|
+
"fix_suggestion": "Disable autoplay by default for minor users. Require explicit user action to play media content. If autoplay is needed, gate it behind an age check and provide prominent controls to pause or stop playback. See DSA Article 28(1) Guidelines.",
|
|
1560
|
+
"penalty": "Up to 6% of annual global turnover (DSA Article 52)",
|
|
1561
|
+
"languages": ["typescript", "javascript", "html", "python", "java", "kotlin", "swift"],
|
|
1562
|
+
"packs": ["eu-dsa"],
|
|
1563
|
+
"fixability": "auto",
|
|
1564
|
+
"transform_type": null,
|
|
1565
|
+
"scaffold_id": null,
|
|
1566
|
+
"guidance_url": "https://www.eu-digital-services-act.com/Digital_Services_Act_Article_28.html"
|
|
1567
|
+
},
|
|
1568
|
+
{
|
|
1569
|
+
"id": "dsa-infinite-scroll-003",
|
|
1570
|
+
"name": "Infinite Scroll Without Minor Gating",
|
|
1571
|
+
"severity": "high",
|
|
1572
|
+
"confidence": "high",
|
|
1573
|
+
"category": "addictive-design",
|
|
1574
|
+
"description": "DSA Article 28(1) Guidelines require continuous content delivery mechanisms (infinite scroll) to be disabled by default for minors. Infinite scroll exploits psychological mechanisms to extend session times beyond user intent.",
|
|
1575
|
+
"patterns": [
|
|
1576
|
+
{ "pattern": "(?:InfiniteScroll|infinite.?scroll|useInfiniteScroll)", "flags": "gi" },
|
|
1577
|
+
{ "pattern": "IntersectionObserver.*(?:load.?more|next.?page|fetch.?more)", "flags": "gi" },
|
|
1578
|
+
{ "pattern": "(?:onEndReached|onScrollEnd|loadMore|infiniteLoad)", "flags": "gi" }
|
|
1579
|
+
],
|
|
1580
|
+
"fix_suggestion": "Disable infinite scroll by default for minor users. Provide pagination or a 'Load More' button that requires deliberate action. Include session time awareness features (e.g., 'You've been scrolling for X minutes'). See DSA Article 28(1) Guidelines.",
|
|
1581
|
+
"penalty": "Up to 6% of annual global turnover (DSA Article 52)",
|
|
1582
|
+
"languages": ["typescript", "javascript", "python", "java", "kotlin", "swift"],
|
|
1583
|
+
"packs": ["eu-dsa"],
|
|
1584
|
+
"fixability": "guided",
|
|
1585
|
+
"transform_type": null,
|
|
1586
|
+
"scaffold_id": null,
|
|
1587
|
+
"guidance_url": "https://www.eu-digital-services-act.com/Digital_Services_Act_Article_28.html"
|
|
1588
|
+
},
|
|
1589
|
+
{
|
|
1590
|
+
"id": "dsa-push-notify-004",
|
|
1591
|
+
"name": "Push Notification Registration Without Minor Checks",
|
|
1592
|
+
"severity": "high",
|
|
1593
|
+
"confidence": "high",
|
|
1594
|
+
"category": "notifications",
|
|
1595
|
+
"description": "DSA Article 28(1) Guidelines require push notifications to be disabled by default for minors, with additional restrictions during core sleep hours. Notification registration without age-gating or time-of-day restrictions violates this requirement.",
|
|
1596
|
+
"patterns": [
|
|
1597
|
+
{ "pattern": "Notification\\.requestPermission", "flags": "g" },
|
|
1598
|
+
{ "pattern": "PushManager\\.subscribe", "flags": "g" },
|
|
1599
|
+
{ "pattern": "(?:firebase\\.messaging|FCM|APNs)\\.(?:getToken|requestPermission|register)", "flags": "gi" },
|
|
1600
|
+
{ "pattern": "registerForRemoteNotifications|requestNotificationPermission", "flags": "g" }
|
|
1601
|
+
],
|
|
1602
|
+
"fix_suggestion": "Disable push notifications by default for minor users. If notifications are enabled, restrict them during sleep hours (typically 10pm-7am based on age). Require explicit opt-in and provide granular notification controls. See DSA Article 28(1) Guidelines.",
|
|
1603
|
+
"penalty": "Up to 6% of annual global turnover (DSA Article 52)",
|
|
1604
|
+
"languages": ["typescript", "javascript", "java", "kotlin", "swift"],
|
|
1605
|
+
"packs": ["eu-dsa"],
|
|
1606
|
+
"fixability": "guided",
|
|
1607
|
+
"transform_type": null,
|
|
1608
|
+
"scaffold_id": null,
|
|
1609
|
+
"guidance_url": "https://www.eu-digital-services-act.com/Digital_Services_Act_Article_28.html"
|
|
1610
|
+
},
|
|
1611
|
+
{
|
|
1612
|
+
"id": "dsa-streak-005",
|
|
1613
|
+
"name": "Streak or Engagement Loop Mechanics",
|
|
1614
|
+
"severity": "high",
|
|
1615
|
+
"confidence": "high",
|
|
1616
|
+
"category": "addictive-design",
|
|
1617
|
+
"description": "DSA Article 28(1) Guidelines require streak mechanics and daily engagement reward loops to be disabled by default for minors. These patterns create compulsive usage through loss aversion and variable reward schedules.",
|
|
1618
|
+
"patterns": [
|
|
1619
|
+
{ "pattern": "(?:streakCount|streak_count|dailyStreak|daily_streak|consecutiveDays|consecutive_days)", "flags": "gi" },
|
|
1620
|
+
{ "pattern": "(?:streakReward|streak_reward|streakBonus|streak_bonus)", "flags": "gi" },
|
|
1621
|
+
{ "pattern": "(?:loseStreak|lose_streak|streakBroken|streak_broken|resetStreak|reset_streak)", "flags": "gi" }
|
|
1622
|
+
],
|
|
1623
|
+
"fix_suggestion": "Disable streak mechanics by default for minor users. If streaks are offered, ensure they do not penalize users for breaks and do not create anxiety about losing progress. Consider replacing streaks with non-compulsive engagement features. See DSA Article 28(1) Guidelines.",
|
|
1624
|
+
"penalty": "Up to 6% of annual global turnover (DSA Article 52)",
|
|
1625
|
+
"languages": ["typescript", "javascript", "python", "java", "kotlin", "swift"],
|
|
1626
|
+
"packs": ["eu-dsa"],
|
|
1627
|
+
"fixability": "guided",
|
|
1628
|
+
"transform_type": null,
|
|
1629
|
+
"scaffold_id": null,
|
|
1630
|
+
"guidance_url": "https://www.eu-digital-services-act.com/Digital_Services_Act_Article_28.html"
|
|
1631
|
+
},
|
|
1632
|
+
{
|
|
1633
|
+
"id": "dsa-recommender-006",
|
|
1634
|
+
"name": "Behavioral Recommendation Without Non-Profiled Alternative",
|
|
1635
|
+
"severity": "critical",
|
|
1636
|
+
"confidence": "medium",
|
|
1637
|
+
"category": "profiling",
|
|
1638
|
+
"description": "DSA Articles 27 and 28 require platforms to offer at least one recommendation option that is not based on profiling and to make it the default for minors. Engagement-based signals (watch time, dwell time, scroll depth) in recommender systems without a non-profiled fallback violate this requirement.",
|
|
1639
|
+
"patterns": [
|
|
1640
|
+
{ "pattern": "(?:watchTime|watch_time|dwellTime|dwell_time|engagementScore|engagement_score)", "flags": "gi" },
|
|
1641
|
+
{ "pattern": "(?:clickThroughRate|click_through_rate|scrollDepth|scroll_depth|viewingHistory|viewing_history)", "flags": "gi" },
|
|
1642
|
+
{ "pattern": "(?:implicitSignal|implicit_signal|behavioralSignal|behavioral_signal)", "flags": "gi" }
|
|
1643
|
+
],
|
|
1644
|
+
"fix_suggestion": "Provide a chronological or editorial feed as the default experience for minor users. If using algorithmic recommendations, ensure a non-profiled alternative is easily accessible and set as default. Prioritize explicit user preferences over implicit behavioral signals. See DSA Articles 27 and 28.",
|
|
1645
|
+
"penalty": "Up to 6% of annual global turnover (DSA Article 52)",
|
|
1646
|
+
"languages": ["typescript", "javascript", "python", "java", "kotlin", "swift"],
|
|
1647
|
+
"packs": ["eu-dsa"],
|
|
1648
|
+
"fixability": "guided",
|
|
1649
|
+
"transform_type": null,
|
|
1650
|
+
"scaffold_id": null,
|
|
1651
|
+
"guidance_url": "https://www.eu-digital-services-act.com/Digital_Services_Act_Article_27.html"
|
|
1652
|
+
},
|
|
1653
|
+
{
|
|
1654
|
+
"id": "dsa-cross-tracking-007",
|
|
1655
|
+
"name": "Cross-Platform Tracking of Minors",
|
|
1656
|
+
"severity": "critical",
|
|
1657
|
+
"confidence": "high",
|
|
1658
|
+
"category": "tracking",
|
|
1659
|
+
"description": "DSA Article 28(1) Guidelines restrict using minors' activity across or beyond the platform unless it serves the best interests of the minor. Cross-site tracking, device fingerprinting, and cross-app identifiers used for profiling minors violate this requirement.",
|
|
1660
|
+
"patterns": [
|
|
1661
|
+
{ "pattern": "(?:thirdPartyCookie|third_party_cookie|crossSiteTrack|cross_site_track)", "flags": "gi" },
|
|
1662
|
+
{ "pattern": "(?:deviceFingerprint|device_fingerprint|browserFingerprint|browser_fingerprint)", "flags": "gi" },
|
|
1663
|
+
{ "pattern": "(?:crossAppId|cross_app_id|advertisingId|advertising_id|IDFA|GAID)", "flags": "gi" }
|
|
1664
|
+
],
|
|
1665
|
+
"fix_suggestion": "Do not use cross-platform tracking identifiers for minors. Disable third-party cookies, device fingerprinting, and advertising identifiers for users known to be under 18. Activity tracking must be limited to the current platform and session. See DSA Article 28(1) Guidelines.",
|
|
1666
|
+
"penalty": "Up to 6% of annual global turnover (DSA Article 52)",
|
|
1667
|
+
"languages": ["typescript", "javascript", "python", "java", "kotlin", "swift"],
|
|
1668
|
+
"packs": ["eu-dsa"],
|
|
1669
|
+
"fixability": "guided",
|
|
1670
|
+
"transform_type": null,
|
|
1671
|
+
"scaffold_id": null,
|
|
1672
|
+
"guidance_url": "https://www.eu-digital-services-act.com/Digital_Services_Act_Article_28.html"
|
|
1673
|
+
},
|
|
1674
|
+
{
|
|
1675
|
+
"id": "dsa-ai-disclosure-008",
|
|
1676
|
+
"name": "AI or Chatbot Interaction Without Disclosure",
|
|
1677
|
+
"severity": "high",
|
|
1678
|
+
"confidence": "medium",
|
|
1679
|
+
"category": "transparency",
|
|
1680
|
+
"description": "DSA Article 28(1) Guidelines require clear, persistent signals when minors are interacting with AI rather than humans. AI features (chatbots, AI-generated responses, AI-powered filters) must be opt-in for minors, not automatically enabled.",
|
|
1681
|
+
"patterns": [
|
|
1682
|
+
{ "pattern": "(?:chatbot|ChatBot|chat_bot|AiAssistant|ai_assistant|virtualAssistant)", "flags": "gi" },
|
|
1683
|
+
{ "pattern": "(?:generateResponse|aiResponse|ai_response|llmOutput|llm_output|completionApi)", "flags": "gi" },
|
|
1684
|
+
{ "pattern": "(?:syntheticContent|synthetic_content|aiGenerated|ai_generated)", "flags": "gi" }
|
|
1685
|
+
],
|
|
1686
|
+
"fix_suggestion": "Display a clear, persistent, child-friendly indicator when a minor is interacting with AI rather than a human. AI chatbots, AI-generated content, and AI-powered features must require explicit opt-in for minor users. See DSA Article 28(1) Guidelines.",
|
|
1687
|
+
"penalty": "Up to 6% of annual global turnover (DSA Article 52)",
|
|
1688
|
+
"languages": ["typescript", "javascript", "python", "java", "kotlin", "swift"],
|
|
1689
|
+
"packs": ["eu-dsa"],
|
|
1690
|
+
"fixability": "guided",
|
|
1691
|
+
"transform_type": null,
|
|
1692
|
+
"scaffold_id": null,
|
|
1693
|
+
"guidance_url": "https://www.eu-digital-services-act.com/Digital_Services_Act_Article_28.html"
|
|
1694
|
+
},
|
|
1695
|
+
{
|
|
1696
|
+
"id": "dsa-ephemeral-009",
|
|
1697
|
+
"name": "Ephemeral or Disappearing Content Feature",
|
|
1698
|
+
"severity": "medium",
|
|
1699
|
+
"confidence": "high",
|
|
1700
|
+
"category": "addictive-design",
|
|
1701
|
+
"description": "DSA Article 28(1) Guidelines require disappearing/ephemeral content features (Stories-style) to be disabled by default for minors. These features create urgency and FOMO, driving compulsive checking behavior.",
|
|
1702
|
+
"patterns": [
|
|
1703
|
+
{ "pattern": "(?:ephemeral|disappearing|selfDestruct|self_destruct|expiringContent|expiring_content)", "flags": "gi" },
|
|
1704
|
+
{ "pattern": "(?:storyDuration|story_duration|storyExpire|story_expire|viewOnce|view_once)", "flags": "gi" },
|
|
1705
|
+
{ "pattern": "(?:ephemeralMessage|ephemeral_message|tempContent|temp_content)", "flags": "gi" }
|
|
1706
|
+
],
|
|
1707
|
+
"fix_suggestion": "Disable disappearing/ephemeral content features by default for minor users. If offered, ensure content expiration does not create artificial urgency. Allow minors to review content without time pressure. See DSA Article 28(1) Guidelines.",
|
|
1708
|
+
"penalty": "Up to 6% of annual global turnover (DSA Article 52)",
|
|
1709
|
+
"languages": ["typescript", "javascript", "python", "java", "kotlin", "swift"],
|
|
1710
|
+
"packs": ["eu-dsa"],
|
|
1711
|
+
"fixability": "guided",
|
|
1712
|
+
"transform_type": null,
|
|
1713
|
+
"scaffold_id": null,
|
|
1714
|
+
"guidance_url": "https://www.eu-digital-services-act.com/Digital_Services_Act_Article_28.html"
|
|
1715
|
+
},
|
|
1716
|
+
{
|
|
1717
|
+
"id": "dsa-read-receipts-010",
|
|
1718
|
+
"name": "Read Receipts or Typing Indicators Enabled by Default",
|
|
1719
|
+
"severity": "medium",
|
|
1720
|
+
"confidence": "high",
|
|
1721
|
+
"category": "privacy",
|
|
1722
|
+
"description": "DSA Article 28(1) Guidelines require read receipts and typing indicators to be disabled by default for minor users. These features create social pressure to respond immediately and can enable monitoring and bullying.",
|
|
1723
|
+
"patterns": [
|
|
1724
|
+
{ "pattern": "(?:readReceipt|read_receipt|readStatus|read_status|seenStatus|seen_status)\\s*[:=]\\s*true", "flags": "gi" },
|
|
1725
|
+
{ "pattern": "(?:typingIndicator|typing_indicator|isTyping|is_typing)\\s*[:=]\\s*true", "flags": "gi" },
|
|
1726
|
+
{ "pattern": "(?:showRead|show_read|markAsRead|mark_as_read).*(?:visible|enabled|default)\\s*[:=]\\s*true", "flags": "gi" }
|
|
1727
|
+
],
|
|
1728
|
+
"fix_suggestion": "Disable read receipts and typing indicators by default for minor users. Allow minors to choose whether to share their read status and typing activity. These features should require explicit opt-in. See DSA Article 28(1) Guidelines.",
|
|
1729
|
+
"penalty": "Up to 6% of annual global turnover (DSA Article 52)",
|
|
1730
|
+
"languages": ["typescript", "javascript", "python", "java", "kotlin", "swift"],
|
|
1731
|
+
"packs": ["eu-dsa"],
|
|
1732
|
+
"fixability": "auto",
|
|
1733
|
+
"transform_type": null,
|
|
1734
|
+
"scaffold_id": null,
|
|
1735
|
+
"guidance_url": "https://www.eu-digital-services-act.com/Digital_Services_Act_Article_28.html"
|
|
1736
|
+
},
|
|
1737
|
+
{
|
|
1738
|
+
"id": "caadca-privacy-001",
|
|
1739
|
+
"name": "Default Tracking Enabled",
|
|
1740
|
+
"severity": "critical",
|
|
1741
|
+
"confidence": "medium",
|
|
1742
|
+
"category": "privacy-defaults",
|
|
1743
|
+
"description": "CAADCA requires default high-privacy settings for children. Tracking, analytics, or telemetry must be OFF by default. Code that initializes tracking as enabled without explicit consent violates CAADCA Section 31(b)(7).",
|
|
1744
|
+
"patterns": [
|
|
1745
|
+
{ "pattern": "(?:trackingEnabled|tracking_enabled|enableTracking|enable_tracking)\\s*[:=]\\s*(?:true|1)", "flags": "gi" },
|
|
1746
|
+
{ "pattern": "(?:analytics|telemetry|tracking)\\s*[:=]\\s*\\{[^}]*(?:enabled|active|on)\\s*:\\s*true", "flags": "gi" },
|
|
1747
|
+
{ "pattern": "(?:doNotTrack|do_not_track|dnt)\\s*[:=]\\s*(?:false|0)", "flags": "gi" },
|
|
1748
|
+
{ "pattern": "(?:optOut|opt_out)\\s*[:=]\\s*false\\b", "flags": "gi" }
|
|
1749
|
+
],
|
|
1750
|
+
"fix_suggestion": "Set tracking, analytics, and telemetry to OFF by default. Require explicit opt-in consent before enabling any data collection. Children should not be tracked by default under CAADCA.",
|
|
1751
|
+
"penalty": "$2,500-$7,500 per affected child",
|
|
1752
|
+
"languages": ["typescript", "javascript", "python", "java", "kotlin", "swift"],
|
|
1753
|
+
"packs": ["caadca"],
|
|
1754
|
+
"fixability": "auto",
|
|
1755
|
+
"transform_type": "set-default",
|
|
1756
|
+
"scaffold_id": null,
|
|
1757
|
+
"guidance_url": null
|
|
1758
|
+
},
|
|
1759
|
+
{
|
|
1760
|
+
"id": "caadca-privacy-002",
|
|
1761
|
+
"name": "Analytics Without Privacy Mode",
|
|
1762
|
+
"severity": "high",
|
|
1763
|
+
"confidence": "low",
|
|
1764
|
+
"category": "privacy-defaults",
|
|
1765
|
+
"description": "CAADCA requires privacy-protective defaults. Analytics SDKs must be initialized with privacy mode, anonymization, or child-safe configuration. Code that initializes analytics without privacy protections may violate CAADCA.",
|
|
1766
|
+
"patterns": [
|
|
1767
|
+
{ "pattern": "(?:GoogleAnalytics|ReactGA|gtag|ga)\\s*(?:\\.|\\()\\s*(?:init|initialize|create)\\s*\\((?![^)]*(?:anonym|privacy|child|coppa|restrict))", "flags": "gi" },
|
|
1768
|
+
{ "pattern": "(?:Amplitude|Mixpanel|Segment|Heap|FullStory)\\s*\\.\\s*(?:init|initialize|setup)\\s*\\((?![^)]*(?:anonym|privacy|child|restrict))", "flags": "gi" },
|
|
1769
|
+
{ "pattern": "(?:anonymizeIp|anonymize_ip|ip_anonymization)\\s*[:=]\\s*(?:false|0)", "flags": "gi" }
|
|
1770
|
+
],
|
|
1771
|
+
"fix_suggestion": "Initialize analytics with privacy mode enabled: anonymize IPs, disable user-level tracking, enable child-safe mode. Consider using privacy-preserving analytics alternatives.",
|
|
1772
|
+
"penalty": "$2,500-$7,500 per affected child",
|
|
1773
|
+
"languages": ["typescript", "javascript", "python", "java", "kotlin", "swift"],
|
|
1774
|
+
"packs": ["caadca"],
|
|
1775
|
+
"fixability": "guided",
|
|
1776
|
+
"transform_type": null,
|
|
1777
|
+
"scaffold_id": null,
|
|
1778
|
+
"guidance_url": null
|
|
1779
|
+
},
|
|
1780
|
+
{
|
|
1781
|
+
"id": "caadca-age-001",
|
|
1782
|
+
"name": "Missing Age Estimation or Verification",
|
|
1783
|
+
"severity": "high",
|
|
1784
|
+
"confidence": "low",
|
|
1785
|
+
"category": "age-estimation",
|
|
1786
|
+
"description": "CAADCA Section 31(b)(1) requires businesses to estimate the age of child users with a reasonable level of certainty. Registration or signup flows that collect no age indicator violate this requirement.",
|
|
1787
|
+
"patterns": [
|
|
1788
|
+
{ "pattern": "(?:createUser|create_user|registerUser|register_user|signUp|sign_up)\\s*\\((?![^)]*(?:age|dob|birthdate|birth_?date|date_?of_?birth))[^)]*\\)", "flags": "gi" },
|
|
1789
|
+
{ "pattern": "(?:onboard|signup|register)(?:Form|Page|Screen|Component|View)\\b(?![^\\n]*(?:age|dob|birthdate|dateOfBirth))", "flags": "gi" }
|
|
1790
|
+
],
|
|
1791
|
+
"fix_suggestion": "Add age estimation to your registration flow: collect date of birth, use an age estimation API, or implement neutral age screening. CAADCA requires 'reasonable certainty' that users are not children.",
|
|
1792
|
+
"penalty": "$2,500-$7,500 per affected child",
|
|
1793
|
+
"languages": ["typescript", "javascript", "python", "java", "kotlin", "swift", "html", "tsx", "jsx"],
|
|
1794
|
+
"packs": ["caadca"],
|
|
1795
|
+
"fixability": "guided",
|
|
1796
|
+
"transform_type": null,
|
|
1797
|
+
"scaffold_id": null,
|
|
1798
|
+
"guidance_url": null
|
|
1799
|
+
},
|
|
1800
|
+
{
|
|
1801
|
+
"id": "caadca-profiling-001",
|
|
1802
|
+
"name": "Behavioral Profiling Without Safeguards",
|
|
1803
|
+
"severity": "critical",
|
|
1804
|
+
"confidence": "medium",
|
|
1805
|
+
"category": "profiling",
|
|
1806
|
+
"description": "CAADCA Section 31(b)(4) prohibits profiling children by default. Code that builds behavioral profiles, interest graphs, or user segments without age-checking or child safeguards violates this requirement.",
|
|
1807
|
+
"patterns": [
|
|
1808
|
+
{ "pattern": "(?:buildProfile|build_profile|createProfile|create_profile|userProfile|user_profile)\\s*(?:\\(|[:=])(?![^\\n]*(?:age|child|minor|under_?18|safeguard))", "flags": "gi" },
|
|
1809
|
+
{ "pattern": "(?:interestGraph|interest_graph|behaviorProfile|behavior_profile|userSegment|user_segment)\\s*[:=]", "flags": "gi" },
|
|
1810
|
+
{ "pattern": "(?:trackBehavior|track_behavior|logActivity|log_activity|recordAction|record_action)\\s*\\((?![^)]*(?:consent|age|child|privacy))", "flags": "gi" }
|
|
1811
|
+
],
|
|
1812
|
+
"fix_suggestion": "Disable behavioral profiling by default for users who may be children. If profiling is necessary, implement age verification first and apply heightened protections for children under 18.",
|
|
1813
|
+
"penalty": "$2,500-$7,500 per affected child",
|
|
1814
|
+
"languages": ["typescript", "javascript", "python", "java", "kotlin", "swift"],
|
|
1815
|
+
"packs": ["caadca"],
|
|
1816
|
+
"fixability": "guided",
|
|
1817
|
+
"transform_type": null,
|
|
1818
|
+
"scaffold_id": null,
|
|
1819
|
+
"guidance_url": null
|
|
1820
|
+
},
|
|
1821
|
+
{
|
|
1822
|
+
"id": "caadca-profiling-002",
|
|
1823
|
+
"name": "Content Recommendation Without Age Filter",
|
|
1824
|
+
"severity": "high",
|
|
1825
|
+
"confidence": "low",
|
|
1826
|
+
"category": "profiling",
|
|
1827
|
+
"description": "CAADCA requires transparent, age-appropriate content recommendations. Recommendation engines that lack age-based filtering or content rating checks may expose children to harmful content.",
|
|
1828
|
+
"patterns": [
|
|
1829
|
+
{ "pattern": "(?:recommend|getRecommendations|get_recommendations|suggestContent|suggest_content)\\s*\\((?![^)]*(?:age|rating|maturity|child|filter))", "flags": "gi" },
|
|
1830
|
+
{ "pattern": "(?:contentFeed|content_feed|forYou|for_you|discover)(?:Algorithm|Engine|Service)\\b(?![^\\n]*(?:age|rating|child|safe))", "flags": "gi" }
|
|
1831
|
+
],
|
|
1832
|
+
"fix_suggestion": "Add age-based filtering to content recommendations. Implement content rating checks and exclude age-inappropriate material for child users. Make recommendation logic transparent per CAADCA requirements.",
|
|
1833
|
+
"penalty": "$2,500-$7,500 per affected child",
|
|
1834
|
+
"languages": ["typescript", "javascript", "python", "java", "kotlin", "swift"],
|
|
1835
|
+
"packs": ["caadca"],
|
|
1836
|
+
"fixability": "guided",
|
|
1837
|
+
"transform_type": null,
|
|
1838
|
+
"scaffold_id": null,
|
|
1839
|
+
"guidance_url": null
|
|
1840
|
+
},
|
|
1841
|
+
{
|
|
1842
|
+
"id": "caadca-darkpat-001",
|
|
1843
|
+
"name": "Manipulative Consent UI",
|
|
1844
|
+
"severity": "critical",
|
|
1845
|
+
"confidence": "medium",
|
|
1846
|
+
"category": "dark-patterns",
|
|
1847
|
+
"description": "CAADCA Section 31(b)(7) prohibits dark patterns that lead children to provide unnecessary personal information, weaken privacy settings, or extend use. UI patterns like 'skip' or 'continue without' on consent screens are manipulative.",
|
|
1848
|
+
"patterns": [
|
|
1849
|
+
{ "pattern": "(?:skip|dismiss|later|not now|maybe later|no thanks|continue without)(?:Consent|Privacy|Permission|Setup)\\b", "flags": "gi" },
|
|
1850
|
+
{ "pattern": ">\\s*(?:Skip|No thanks|Not now|Maybe later|Continue without|I don't care)\\s*<", "flags": "gi" },
|
|
1851
|
+
{ "pattern": "(?:text-(?:xs|sm)|opacity-(?:50|60|70)|text-gray-(?:300|400)|color:\\s*#(?:ccc|ddd|999)).*(?:decline|reject|opt.?out|privacy)", "flags": "gi" }
|
|
1852
|
+
],
|
|
1853
|
+
"fix_suggestion": "Present consent choices with equal visual weight. Don't make privacy-protective options harder to find or smaller than privacy-invasive options. Avoid manipulative language that pressures children to share data.",
|
|
1854
|
+
"penalty": "$2,500-$7,500 per affected child",
|
|
1855
|
+
"languages": ["typescript", "javascript", "html", "tsx", "jsx", "vue", "svelte"],
|
|
1856
|
+
"packs": ["caadca"],
|
|
1857
|
+
"fixability": "flag-only",
|
|
1858
|
+
"transform_type": null,
|
|
1859
|
+
"scaffold_id": null,
|
|
1860
|
+
"guidance_url": null
|
|
1861
|
+
},
|
|
1862
|
+
{
|
|
1863
|
+
"id": "caadca-darkpat-002",
|
|
1864
|
+
"name": "Urgency-Creating Countdown Timer",
|
|
1865
|
+
"severity": "high",
|
|
1866
|
+
"confidence": "medium",
|
|
1867
|
+
"category": "dark-patterns",
|
|
1868
|
+
"description": "CAADCA prohibits dark patterns that exploit children. Countdown timers on offers, limited-time promotions, or fear-of-missing-out (FOMO) mechanics are manipulative design patterns targeting children.",
|
|
1869
|
+
"patterns": [
|
|
1870
|
+
{ "pattern": "(?:countdown|timer|timeLeft|time_left|expiresIn|expires_in|hurry|limited.?time|act.?now|last.?chance)(?:Component|Timer|Widget|Banner)\\b", "flags": "gi" },
|
|
1871
|
+
{ "pattern": "(?:setInterval|setTimeout)\\s*\\([^)]*(?:countdown|timer|remaining|expir|urgent|hurry)", "flags": "gi" },
|
|
1872
|
+
{ "pattern": "(?:FOMO|fomo|scarcity|urgency)(?:Banner|Modal|Popup|Alert|Notification)\\b", "flags": "gi" }
|
|
1873
|
+
],
|
|
1874
|
+
"fix_suggestion": "Remove urgency-creating countdown timers, FOMO mechanics, and limited-time pressure from child-facing interfaces. CAADCA prohibits manipulative design that exploits children's vulnerability to pressure tactics.",
|
|
1875
|
+
"penalty": "$2,500-$7,500 per affected child",
|
|
1876
|
+
"languages": ["typescript", "javascript", "html", "tsx", "jsx", "vue", "svelte"],
|
|
1877
|
+
"packs": ["caadca"],
|
|
1878
|
+
"fixability": "flag-only",
|
|
1879
|
+
"transform_type": null,
|
|
1880
|
+
"scaffold_id": null,
|
|
1881
|
+
"guidance_url": null
|
|
1882
|
+
},
|
|
1883
|
+
{
|
|
1884
|
+
"id": "caadca-darkpat-003",
|
|
1885
|
+
"name": "Confirmshaming Pattern",
|
|
1886
|
+
"severity": "medium",
|
|
1887
|
+
"confidence": "medium",
|
|
1888
|
+
"category": "dark-patterns",
|
|
1889
|
+
"description": "CAADCA prohibits manipulative design patterns that shame children into making privacy-invasive choices. Confirmshaming uses guilt-inducing language on opt-out or decline buttons.",
|
|
1890
|
+
"patterns": [
|
|
1891
|
+
{ "pattern": ">\\s*(?:No,? I don't want|I prefer not to|I'll miss out|No,? I hate saving|I don't like)\\s*", "flags": "gi" },
|
|
1892
|
+
{ "pattern": "(?:confirmshaming|confirm_shaming|guiltTrip|guilt_trip|shameButton|shame_button)\\b", "flags": "gi" }
|
|
1893
|
+
],
|
|
1894
|
+
"fix_suggestion": "Use neutral, non-manipulative language for all opt-out and decline options. Replace confirmshaming copy with straightforward alternatives like 'No thanks' or 'Decline'.",
|
|
1895
|
+
"penalty": "$2,500-$7,500 per affected child",
|
|
1896
|
+
"languages": ["typescript", "javascript", "html", "tsx", "jsx", "vue", "svelte"],
|
|
1897
|
+
"packs": ["caadca"],
|
|
1898
|
+
"fixability": "flag-only",
|
|
1899
|
+
"transform_type": null,
|
|
1900
|
+
"scaffold_id": null,
|
|
1901
|
+
"guidance_url": null
|
|
1902
|
+
},
|
|
1903
|
+
{
|
|
1904
|
+
"id": "caadca-geo-001",
|
|
1905
|
+
"name": "Precise Geolocation Without Purpose",
|
|
1906
|
+
"severity": "critical",
|
|
1907
|
+
"confidence": "medium",
|
|
1908
|
+
"category": "geolocation",
|
|
1909
|
+
"description": "CAADCA Section 31(b)(3) restricts collecting children's precise geolocation. Code that requests fine-grained location (GPS) without a clear, necessary purpose violates this requirement.",
|
|
1910
|
+
"patterns": [
|
|
1911
|
+
{ "pattern": "(?:getCurrentPosition|watchPosition|geolocation\\.get)\\s*\\((?![^)]*(?:coarse|approximate|city|region|purpose|reason))", "flags": "gi" },
|
|
1912
|
+
{ "pattern": "(?:enableHighAccuracy|high_accuracy)\\s*[:=]\\s*true", "flags": "gi" },
|
|
1913
|
+
{ "pattern": "(?:ACCESS_FINE_LOCATION|kCLLocationAccuracyBest|kCLLocationAccuracyNearestTenMeters)", "flags": "g" },
|
|
1914
|
+
{ "pattern": "(?:latitude|longitude|lat|lng|coordinates).*(?:store|save|persist|track|log|send|upload)\\s*\\(", "flags": "gi" }
|
|
1915
|
+
],
|
|
1916
|
+
"fix_suggestion": "Use coarse/approximate location (city-level) instead of precise GPS coordinates. Only request fine-grained location when strictly necessary for core functionality. Never persistently track a child's location.",
|
|
1917
|
+
"penalty": "$2,500-$7,500 per affected child",
|
|
1918
|
+
"languages": ["typescript", "javascript", "python", "java", "kotlin", "swift"],
|
|
1919
|
+
"packs": ["caadca"],
|
|
1920
|
+
"fixability": "guided",
|
|
1921
|
+
"transform_type": null,
|
|
1922
|
+
"scaffold_id": null,
|
|
1923
|
+
"guidance_url": null
|
|
1924
|
+
},
|
|
1925
|
+
{
|
|
1926
|
+
"id": "caadca-datamin-001",
|
|
1927
|
+
"name": "Excessive Data Collection",
|
|
1928
|
+
"severity": "high",
|
|
1929
|
+
"confidence": "low",
|
|
1930
|
+
"category": "data-minimization",
|
|
1931
|
+
"description": "CAADCA Section 31(b)(3) requires data minimization — only collect personal information that is reasonably necessary. Code that collects extensive personal data fields beyond what the service needs may violate this requirement.",
|
|
1932
|
+
"patterns": [
|
|
1933
|
+
{ "pattern": "(?:collectData|collect_data|gatherInfo|gather_info|harvestData|harvest_data)\\s*\\(", "flags": "gi" },
|
|
1934
|
+
{ "pattern": "(?:required|mandatory)\\s*[:=]\\s*true[^\\n]*(?:phone|address|school|gender|ethnicity|income|ssn|social_security)", "flags": "gi" },
|
|
1935
|
+
{ "pattern": "(?:deviceFingerprint|device_fingerprint|browserFingerprint|browser_fingerprint|canvasFingerprint|canvas_fingerprint)\\b", "flags": "gi" }
|
|
1936
|
+
],
|
|
1937
|
+
"fix_suggestion": "Only collect data that is strictly necessary for the service's core functionality. Remove collection of non-essential fields. Implement data minimization by design per CAADCA requirements.",
|
|
1938
|
+
"penalty": "$2,500-$7,500 per affected child",
|
|
1939
|
+
"languages": ["typescript", "javascript", "python", "java", "kotlin", "swift"],
|
|
1940
|
+
"packs": ["caadca"],
|
|
1941
|
+
"fixability": "flag-only",
|
|
1942
|
+
"transform_type": null,
|
|
1943
|
+
"scaffold_id": null,
|
|
1944
|
+
"guidance_url": null
|
|
1945
|
+
},
|
|
1946
|
+
{
|
|
1947
|
+
"id": "caadca-iap-001",
|
|
1948
|
+
"name": "One-Click Purchase Without Confirmation",
|
|
1949
|
+
"severity": "critical",
|
|
1950
|
+
"confidence": "high",
|
|
1951
|
+
"category": "in-app-purchases",
|
|
1952
|
+
"description": "CAADCA requires friction in purchase flows for children. One-click or instant purchases without a confirmation step can lead to unauthorized spending by minors.",
|
|
1953
|
+
"patterns": [
|
|
1954
|
+
{ "pattern": "(?:oneClickPurchase|one_click_purchase|instantPurchase|instant_purchase|quickBuy|quick_buy)\\b", "flags": "gi" },
|
|
1955
|
+
{ "pattern": "(?:purchase|buy|checkout|pay)\\s*\\((?![^)]*(?:confirm|verify|approve|consent|auth))[^)]*\\)", "flags": "gi" },
|
|
1956
|
+
{ "pattern": "(?:skipConfirmation|skip_confirmation|autoCharge|auto_charge|autoPurchase|auto_purchase)\\s*[:=]\\s*true", "flags": "gi" }
|
|
1957
|
+
],
|
|
1958
|
+
"fix_suggestion": "Add a confirmation step before any purchase. Require explicit confirmation (e.g., 'Are you sure?' dialog) before processing payments. For children, require parental authentication for purchases.",
|
|
1959
|
+
"penalty": "$2,500-$7,500 per affected child",
|
|
1960
|
+
"languages": ["typescript", "javascript", "python", "java", "kotlin", "swift"],
|
|
1961
|
+
"packs": ["caadca"],
|
|
1962
|
+
"fixability": "guided",
|
|
1963
|
+
"transform_type": null,
|
|
1964
|
+
"scaffold_id": null,
|
|
1965
|
+
"guidance_url": null
|
|
1966
|
+
},
|
|
1967
|
+
{
|
|
1968
|
+
"id": "caadca-iap-002",
|
|
1969
|
+
"name": "In-App Purchase Without Parental Gate",
|
|
1970
|
+
"severity": "critical",
|
|
1971
|
+
"confidence": "medium",
|
|
1972
|
+
"category": "in-app-purchases",
|
|
1973
|
+
"description": "CAADCA requires parental consent for financial transactions involving children. In-app purchase flows that don't check for age or parental authorization expose children to unauthorized spending.",
|
|
1974
|
+
"patterns": [
|
|
1975
|
+
{ "pattern": "(?:makePurchase|make_purchase|processPurchase|process_purchase|completePurchase|complete_purchase)\\s*\\((?![^)]*(?:parent|guardian|age|minor|child|consent))", "flags": "gi" },
|
|
1976
|
+
{ "pattern": "(?:virtualCurrency|virtual_currency|coins|gems|vbucks|robux).*(?:purchase|buy|spend)\\s*\\((?![^)]*(?:parent|guardian|consent|auth))", "flags": "gi" }
|
|
1977
|
+
],
|
|
1978
|
+
"fix_suggestion": "Add parental authentication or consent before allowing in-app purchases for users who may be children. Implement age-gating and require parental approval for virtual currency purchases.",
|
|
1979
|
+
"penalty": "$2,500-$7,500 per affected child",
|
|
1980
|
+
"languages": ["typescript", "javascript", "python", "java", "kotlin", "swift"],
|
|
1981
|
+
"packs": ["caadca"],
|
|
1982
|
+
"fixability": "guided",
|
|
1983
|
+
"transform_type": null,
|
|
1984
|
+
"scaffold_id": null,
|
|
1985
|
+
"guidance_url": null
|
|
1986
|
+
},
|
|
1987
|
+
{
|
|
1988
|
+
"id": "caadca-notify-001",
|
|
1989
|
+
"name": "Push Notifications Without Frequency Limit",
|
|
1990
|
+
"severity": "medium",
|
|
1991
|
+
"confidence": "low",
|
|
1992
|
+
"category": "notifications",
|
|
1993
|
+
"description": "CAADCA prohibits features that encourage excessive use by children. Push notifications without frequency limits or quiet hours can manipulate children into compulsive engagement.",
|
|
1994
|
+
"patterns": [
|
|
1995
|
+
{ "pattern": "(?:sendNotification|send_notification|pushNotification|push_notification|sendPush|send_push)\\s*\\((?![^)]*(?:limit|throttle|frequency|quiet|schedule|age|child))", "flags": "gi" },
|
|
1996
|
+
{ "pattern": "(?:notificationFrequency|notification_frequency|pushFrequency|push_frequency)\\s*[:=]\\s*(?:unlimited|0|null|undefined)", "flags": "gi" },
|
|
1997
|
+
{ "pattern": "(?:streakReminder|streak_reminder|comeBackNotification|come_back_notification|missYou|miss_you)\\b", "flags": "gi" }
|
|
1998
|
+
],
|
|
1999
|
+
"fix_suggestion": "Implement notification frequency limits and quiet hours for child users. Disable streak-based and FOMO notifications. Allow children to control notification settings easily.",
|
|
2000
|
+
"penalty": "$2,500-$7,500 per affected child",
|
|
2001
|
+
"languages": ["typescript", "javascript", "python", "java", "kotlin", "swift"],
|
|
2002
|
+
"packs": ["caadca"],
|
|
2003
|
+
"fixability": "guided",
|
|
2004
|
+
"transform_type": null,
|
|
2005
|
+
"scaffold_id": null,
|
|
2006
|
+
"guidance_url": null
|
|
2007
|
+
},
|
|
2008
|
+
{
|
|
2009
|
+
"id": "caadca-transparency-001",
|
|
2010
|
+
"name": "Missing Child-Friendly Privacy Notice",
|
|
2011
|
+
"severity": "high",
|
|
2012
|
+
"confidence": "low",
|
|
2013
|
+
"category": "transparency",
|
|
2014
|
+
"description": "CAADCA Section 31(b)(6) requires privacy information to be provided in clear, age-appropriate language. Registration forms and data collection points must include prominent, child-friendly privacy disclosures.",
|
|
2015
|
+
"patterns": [
|
|
2016
|
+
{ "pattern": "<form[^>]*(?:id|class|name)\\s*=\\s*[\"'][^\"']*(?:register|signup|sign[-_]up|create[-_]account)[^\"']*[\"'](?![\\s\\S]{0,500}(?:privacy|data|information|collected|shared|used))", "flags": "gi" },
|
|
2017
|
+
{ "pattern": "(?:termsAndConditions|terms_and_conditions|tosAccepted|tos_accepted)\\s*(?:&&|\\|\\|)\\s*(?!.*(?:privacyPolicy|privacy_policy|privacyNotice|privacy_notice))", "flags": "gi" }
|
|
2018
|
+
],
|
|
2019
|
+
"fix_suggestion": "Add a clear, child-friendly privacy notice to all data collection points. Use simple language explaining what data is collected, why, and who has access. Include a prominent link to your privacy policy.",
|
|
2020
|
+
"penalty": "$2,500-$7,500 per affected child",
|
|
2021
|
+
"languages": ["typescript", "javascript", "html", "tsx", "jsx", "vue", "svelte"],
|
|
2022
|
+
"packs": ["caadca"],
|
|
2023
|
+
"fixability": "guided",
|
|
2024
|
+
"transform_type": null,
|
|
2025
|
+
"scaffold_id": null,
|
|
2026
|
+
"guidance_url": null
|
|
2027
|
+
},
|
|
2028
|
+
{
|
|
2029
|
+
"id": "caadca-ads-001",
|
|
2030
|
+
"name": "Targeted Advertising to Children",
|
|
2031
|
+
"severity": "critical",
|
|
2032
|
+
"confidence": "medium",
|
|
2033
|
+
"category": "advertising",
|
|
2034
|
+
"description": "CAADCA Section 31(b)(4) prohibits profiling children for targeted advertising. Code that serves behavioral or targeted ads without age verification violates this requirement.",
|
|
2035
|
+
"patterns": [
|
|
2036
|
+
{ "pattern": "(?:targetedAd|targeted_ad|personalizedAd|personalized_ad|behavioralAd|behavioral_ad)\\s*(?:\\(|[:=])(?![^\\n]*(?:age|child|minor|disable|restrict))", "flags": "gi" },
|
|
2037
|
+
{ "pattern": "(?:AdMob|GoogleAds|FacebookAds|adNetwork|ad_network)\\s*\\.\\s*(?:show|display|load|request)\\s*\\((?![^)]*(?:child|minor|age|coppa|restrict))", "flags": "gi" },
|
|
2038
|
+
{ "pattern": "(?:adPersonalization|ad_personalization|adTargeting|ad_targeting)\\s*[:=]\\s*(?:true|1|'enabled'|\"enabled\")", "flags": "gi" }
|
|
2039
|
+
],
|
|
2040
|
+
"fix_suggestion": "Disable targeted and behavioral advertising for users who may be children. Use only contextual (non-personalized) ads. Implement age verification before serving personalized advertising.",
|
|
2041
|
+
"penalty": "$2,500-$7,500 per affected child",
|
|
2042
|
+
"languages": ["typescript", "javascript", "python", "java", "kotlin", "swift"],
|
|
2043
|
+
"packs": ["caadca"],
|
|
2044
|
+
"fixability": "guided",
|
|
2045
|
+
"transform_type": null,
|
|
2046
|
+
"scaffold_id": null,
|
|
2047
|
+
"guidance_url": null
|
|
2048
|
+
},
|
|
2049
|
+
{
|
|
2050
|
+
"id": "AU-OSA-001",
|
|
2051
|
+
"name": "Missing Age Verification at Registration",
|
|
2052
|
+
"severity": "critical",
|
|
2053
|
+
"confidence": "medium",
|
|
2054
|
+
"category": "online-safety",
|
|
2055
|
+
"description": "Account creation or signup flow detected without age verification. The AU Online Safety Act 2021 (as amended 2024) s.63B requires social media platforms to take reasonable steps to verify that users are aged 16 or over before allowing account creation. Registration flows must include age assurance mechanisms — not just self-declaration.",
|
|
2056
|
+
"patterns": [
|
|
2057
|
+
{ "pattern": "(?:createAccount|create_account|registerUser|register_user)\\s*\\((?![^)]*(?:age|dob|dateOfBirth|date_of_birth|birthDate|birth_date|ageVerif|ageCheck|age_check|verifyAge|verify_age))[^)]*\\)", "flags": "gi" },
|
|
2058
|
+
{ "pattern": "(?:signUp|sign_up|onboardUser|onboard_user)\\s*\\((?![^)]*(?:age|dob|dateOfBirth|date_of_birth|birthDate|birth_date|ageVerif|ageCheck|verify_age))[^)]*\\)", "flags": "gi" },
|
|
2059
|
+
{ "pattern": "(?:UserRegistration|AccountCreation|SignupService)\\s*\\.\\s*(?:create|register|submit|process)\\s*\\((?![^)]*(?:age|birth|dob|verif))", "flags": "gi" },
|
|
2060
|
+
{ "pattern": "INSERT\\s+INTO\\s+(?:users|accounts|members)\\s*\\((?![^)]*(?:age|dob|birth_date|date_of_birth))[^)]*\\)\\s*VALUES", "flags": "gi" },
|
|
2061
|
+
{ "pattern": "(?:router|app)\\.(?:post|put)\\s*\\(\\s*['\"](?:\\/register|\\/signup|\\/create-account)['\"](?![^\\n]*(?:ageGate|age_gate|ageVerif|age_verif|checkAge|check_age))", "flags": "gi" }
|
|
2062
|
+
],
|
|
2063
|
+
"fix_suggestion": "Add an age verification step before account creation. Under AU OSA s.63B, social media services must use reasonably effective age assurance to prevent under-16s from creating accounts. Implement identity-based verification (document check, biometric estimation, or digital ID) — not just self-declaration.",
|
|
2064
|
+
"penalty": "Up to AUD $49.5M (body corporate) or AUD $2.475M (individual)",
|
|
2065
|
+
"languages": ["typescript", "javascript", "python", "java", "swift", "kotlin"],
|
|
2066
|
+
"packs": ["au-osa"],
|
|
2067
|
+
"fixability": "flag-only",
|
|
2068
|
+
"transform_type": null,
|
|
2069
|
+
"scaffold_id": null,
|
|
2070
|
+
"guidance_url": null
|
|
2071
|
+
},
|
|
2072
|
+
{
|
|
2073
|
+
"id": "AU-OSA-002",
|
|
2074
|
+
"name": "Self-Declaration Age Check",
|
|
2075
|
+
"severity": "high",
|
|
2076
|
+
"confidence": "medium",
|
|
2077
|
+
"category": "online-safety",
|
|
2078
|
+
"description": "Reliance on self-declared age (checkbox, simple DOB field without verification) detected. The AU Online Safety Act 2021 (as amended 2024) s.63C requires 'reasonably effective' age assurance — simple self-declaration (e.g., 'I am over 16' checkbox or unverified date-of-birth entry) does not meet this threshold. Platforms must use technology-based age assurance methods.",
|
|
2079
|
+
"patterns": [
|
|
2080
|
+
{ "pattern": "(?:isOver16|is_over_16|isOver18|is_over_18|isAdult|is_adult|ageConfirmed|age_confirmed)\\s*[:=]\\s*(?:true|false|checkbox|input)", "flags": "gi" },
|
|
2081
|
+
{ "pattern": "(?:ageGate|age_gate|ageCheck|age_check)\\s*[:=]\\s*['\"]?(?:self[_-]?declar|checkbox|honor|trust|confirm)['\"]?", "flags": "gi" },
|
|
2082
|
+
{ "pattern": "<input[^>]*(?:type=['\"](?:checkbox|date)['\"])[^>]*(?:age|birth|dob|over.?1[68])[^>]*>", "flags": "gi" },
|
|
2083
|
+
{ "pattern": "(?:confirmAge|confirm_age|declareAge|declare_age|ageDeclaration|age_declaration)\\s*(?:=|:|\\()", "flags": "gi" },
|
|
2084
|
+
{ "pattern": "(?:age_?verification_?method|ageVerificationMethod)\\s*[:=]\\s*['\"](?:self|declaration|checkbox|honor|dob_only)['\"]", "flags": "gi" }
|
|
2085
|
+
],
|
|
2086
|
+
"fix_suggestion": "Replace self-declaration age checks with a reasonably effective age assurance method. AU OSA s.63C requires technology-based verification such as biometric age estimation, digital identity document checks, or government-issued digital ID verification. A simple checkbox or unverified DOB field is insufficient.",
|
|
2087
|
+
"penalty": "Up to AUD $49.5M (body corporate) or AUD $2.475M (individual)",
|
|
2088
|
+
"languages": ["typescript", "javascript", "python", "java", "swift", "kotlin"],
|
|
2089
|
+
"packs": ["au-osa"],
|
|
2090
|
+
"fixability": "flag-only",
|
|
2091
|
+
"transform_type": null,
|
|
2092
|
+
"scaffold_id": null,
|
|
2093
|
+
"guidance_url": null
|
|
2094
|
+
},
|
|
2095
|
+
{
|
|
2096
|
+
"id": "AU-OSA-003",
|
|
2097
|
+
"name": "Missing Under-16 Account Purge",
|
|
2098
|
+
"severity": "critical",
|
|
2099
|
+
"confidence": "low",
|
|
2100
|
+
"category": "online-safety",
|
|
2101
|
+
"description": "Underage user detection without corresponding account deletion or data purge mechanism. When a social media platform determines a user is under 16, the AU Online Safety Act 2021 (as amended 2024) s.63D requires the platform to close the account and delete associated personal data. Failing to purge underage accounts exposes the platform to enforcement action by the eSafety Commissioner.",
|
|
2102
|
+
"patterns": [
|
|
2103
|
+
{ "pattern": "(?:userAge|user_age|accountAge|account_age)\\s*(?:<|<=)\\s*1[68](?![^\\n]*(?:delete|purge|remove|close|disable|suspend|deactivate|terminate))", "flags": "gi" },
|
|
2104
|
+
{ "pattern": "(?:isMinor|is_minor|isUnderage|is_underage|isChild|is_child)\\s*[:=]\\s*true(?![^\\n]*(?:delete|purge|remove|close|disable|suspend|deactivate))", "flags": "gi" },
|
|
2105
|
+
{ "pattern": "(?:age|userAge|user_age)\\s*(?:<|<=)\\s*1[68]\\s*(?:\\)|\\{|&&|\\|\\|)(?![\\s\\S]{0,200}(?:deleteAccount|delete_account|purgeUser|purge_user|removeData|remove_data|closeAccount|close_account))", "flags": "gi" },
|
|
2106
|
+
{ "pattern": "(?:underage_?detected|minorDetected|minor_detected|failed_?age_?check|failedAgeCheck)\\s*(?:=|:|\\()(?![^\\n]*(?:delete|purge|remove|close|wipe|destroy))", "flags": "gi" }
|
|
2107
|
+
],
|
|
2108
|
+
"fix_suggestion": "When a user is determined to be under 16, immediately close the account and delete all associated personal data. Implement an automated purge pipeline triggered by underage detection. AU OSA s.63D requires platforms to take reasonable steps to close accounts and remove data of users found to be under the minimum age.",
|
|
2109
|
+
"penalty": "Up to AUD $49.5M (body corporate) or AUD $2.475M (individual)",
|
|
2110
|
+
"languages": ["typescript", "javascript", "python", "java", "swift", "kotlin"],
|
|
2111
|
+
"packs": ["au-osa"],
|
|
2112
|
+
"fixability": "flag-only",
|
|
2113
|
+
"transform_type": null,
|
|
2114
|
+
"scaffold_id": null,
|
|
2115
|
+
"guidance_url": null
|
|
2116
|
+
},
|
|
2117
|
+
{
|
|
2118
|
+
"id": "AU-OSA-004",
|
|
2119
|
+
"name": "Class 1/Class 2 Content Without Moderation",
|
|
2120
|
+
"severity": "critical",
|
|
2121
|
+
"confidence": "medium",
|
|
2122
|
+
"category": "online-safety",
|
|
2123
|
+
"description": "User-generated content upload or submission detected without content moderation, classification, or safety scanning. The AU Online Safety Act 2021 Schedule 2 classifies illegal content as Class 1 (e.g., CSAM, terrorism) and harmful content as Class 2 (e.g., violence, self-harm). Platforms must proactively detect and prevent distribution of such material under s.109 (BOSE determination).",
|
|
2124
|
+
"patterns": [
|
|
2125
|
+
{ "pattern": "(?:uploadContent|upload_content|submitPost|submit_post|uploadImage|upload_image|uploadVideo|upload_video|uploadMedia|upload_media)\\s*\\((?![^)]*(?:moderate|classify|scan|filter|review|check|safety|csam|hash))", "flags": "gi" },
|
|
2126
|
+
{ "pattern": "(?:createPost|create_post|publishContent|publish_content|postContent|post_content)\\s*\\((?![^)]*(?:moderate|classify|scan|filter|review|check|safety))", "flags": "gi" },
|
|
2127
|
+
{ "pattern": "(?:multer|formidable|busboy|express-fileupload)\\s*\\((?![^\\n]*(?:contentModerat|content_moderat|photoScan|photo_scan|imageSafety|image_safety|hashCheck|hash_check))", "flags": "gi" },
|
|
2128
|
+
{ "pattern": "(?:S3|GCS|Azure|CloudStorage)\\.(?:upload|putObject|put_object|createBlob)\\s*\\((?![^\\n]*(?:moderate|scan|classify|filter|safety))", "flags": "gi" }
|
|
2129
|
+
],
|
|
2130
|
+
"fix_suggestion": "Implement content moderation before or immediately after content upload. Use automated scanning for Class 1 material (CSAM hash matching via PhotoDNA or similar), and classification/filtering for Class 2 material (violence, self-harm). AU OSA Schedule 2 and BOSE s.109 require proactive detection and rapid removal.",
|
|
2131
|
+
"penalty": "Up to AUD $49.5M (body corporate) or AUD $2.475M (individual)",
|
|
2132
|
+
"languages": ["typescript", "javascript", "python", "java", "swift", "kotlin"],
|
|
2133
|
+
"packs": ["au-osa"],
|
|
2134
|
+
"fixability": "flag-only",
|
|
2135
|
+
"transform_type": null,
|
|
2136
|
+
"scaffold_id": null,
|
|
2137
|
+
"guidance_url": null
|
|
2138
|
+
},
|
|
2139
|
+
{
|
|
2140
|
+
"id": "AU-OSA-005",
|
|
2141
|
+
"name": "Content Removal SLA Non-Compliance",
|
|
2142
|
+
"severity": "high",
|
|
2143
|
+
"confidence": "medium",
|
|
2144
|
+
"category": "online-safety",
|
|
2145
|
+
"description": "Content reporting or flagging mechanism detected without time-bound removal or escalation workflow. The AU Online Safety Act 2021 s.88 empowers the eSafety Commissioner to issue removal notices requiring compliance within 24 hours. Platforms must have automated escalation and removal pipelines to meet this SLA.",
|
|
2146
|
+
"patterns": [
|
|
2147
|
+
{ "pattern": "(?:reportContent|report_content|flagContent|flag_content|reportPost|report_post|flagPost|flag_post)\\s*(?:=|:|\\()(?![^\\n]*(?:autoRemove|auto_remove|queueReview|queue_review|removalSLA|removal_sla|escalat|removeWithin|remove_within|timer|deadline|sla))", "flags": "gi" },
|
|
2148
|
+
{ "pattern": "(?:contentReport|content_report|flaggedContent|flagged_content|reportQueue|report_queue)\\s*[:=]\\s*\\{(?![^}]*(?:sla|deadline|ttl|timeout|escalat|autoRemov|auto_remov|maxAge|max_age|expir))", "flags": "gi" },
|
|
2149
|
+
{ "pattern": "(?:handleReport|handle_report|processFlag|process_flag|reviewContent|review_content)\\s*\\((?![^)]*(?:sla|deadline|timeout|urgent|priority|escalat))", "flags": "gi" },
|
|
2150
|
+
{ "pattern": "(?:abuse_?report|safety_?report|harm_?report)\\s*(?:=|:|\\()(?![^\\n]*(?:24.?h|twenty.?four|sla|deadline|urgent|escalat|auto.?remov))", "flags": "gi" }
|
|
2151
|
+
],
|
|
2152
|
+
"fix_suggestion": "Implement a time-bound content removal pipeline. AU OSA s.88 removal notices require compliance within 24 hours. Add SLA tracking, automated escalation for unresolved reports, and priority queuing for eSafety Commissioner notices. Ensure removal timestamps are logged for compliance auditing.",
|
|
2153
|
+
"penalty": "Up to AUD $49.5M (body corporate) or AUD $2.475M (individual)",
|
|
2154
|
+
"languages": ["typescript", "javascript", "python", "java", "swift", "kotlin"],
|
|
2155
|
+
"packs": ["au-osa"],
|
|
2156
|
+
"fixability": "flag-only",
|
|
2157
|
+
"transform_type": null,
|
|
2158
|
+
"scaffold_id": null,
|
|
2159
|
+
"guidance_url": null
|
|
2160
|
+
},
|
|
2161
|
+
{
|
|
2162
|
+
"id": "AU-OSA-006",
|
|
2163
|
+
"name": "Minor Data Retention Without TTL",
|
|
2164
|
+
"severity": "high",
|
|
2165
|
+
"confidence": "medium",
|
|
2166
|
+
"category": "online-safety",
|
|
2167
|
+
"description": "Storage of child or minor user data without time-to-live, retention policy, or automatic deletion mechanism. The AU Online Safety Act 2021 BOSE determination (s.109) and Privacy Act 1988 APP 11.2 require data minimization and defined retention limits for personal information, particularly for minors. Data must not be kept longer than necessary.",
|
|
2168
|
+
"patterns": [
|
|
2169
|
+
{ "pattern": "(?:childData|child_data|minorData|minor_data|kidProfile|kid_profile|childProfile|child_profile|underageData|underage_data)\\s*[:=]\\s*\\{(?![^}]*(?:ttl|expir|retention|deleteAfter|delete_after|maxAge|max_age|purge|cleanup))", "flags": "gi" },
|
|
2170
|
+
{ "pattern": "(?:userData|user_data|userProfile|user_profile|accountData|account_data)\\s*[:=]\\s*\\{[^}]*(?:isMinor|is_minor|isChild|is_child|age\\s*[:=]\\s*\\d)(?![^}]*(?:ttl|expir|retention|deleteAfter|delete_after|purge))", "flags": "gi" },
|
|
2171
|
+
{ "pattern": "(?:CREATE\\s+TABLE|createTable|defineSchema|Schema)\\s*[^;]*(?:child|minor|kid|youth|teen)[^;]*(?![^;]*(?:ttl|expir|retention|deleted_at|purge_at|cleanup))", "flags": "gi" },
|
|
2172
|
+
{ "pattern": "(?:store|save|persist|cache|retain)(?:Child|Minor|Youth|Kid|Teen)(?:Data|Profile|Record|Info)\\s*\\((?![^)]*(?:ttl|expir|retention|maxAge|max_age|purge))", "flags": "gi" }
|
|
2173
|
+
],
|
|
2174
|
+
"fix_suggestion": "Add retention limits (TTL, expiresAt, or retention policy) to all data stores containing minor user information. Implement automated purge mechanisms. AU OSA BOSE (s.109) expects data minimization, and Privacy Act 1988 APP 11.2 requires deletion when data is no longer needed for its collected purpose.",
|
|
2175
|
+
"penalty": "Up to AUD $49.5M (body corporate) or AUD $2.475M (individual)",
|
|
2176
|
+
"languages": ["typescript", "javascript", "python", "java", "swift", "kotlin"],
|
|
2177
|
+
"packs": ["au-osa"],
|
|
2178
|
+
"fixability": "flag-only",
|
|
2179
|
+
"transform_type": null,
|
|
2180
|
+
"scaffold_id": null,
|
|
2181
|
+
"guidance_url": null
|
|
2182
|
+
},
|
|
2183
|
+
{
|
|
2184
|
+
"id": "AU-OSA-007",
|
|
2185
|
+
"name": "Missing Safety Impact Assessment Hook",
|
|
2186
|
+
"severity": "medium",
|
|
2187
|
+
"confidence": "low",
|
|
2188
|
+
"category": "online-safety",
|
|
2189
|
+
"description": "Feature launch, deployment, or rollout code detected without a safety assessment or risk evaluation step. The AU Online Safety Act 2021 BOSE determination (s.109) expects platforms to proactively assess the safety impact of new features before deployment, particularly features that affect minors or user-generated content.",
|
|
2190
|
+
"patterns": [
|
|
2191
|
+
{ "pattern": "(?:featureLaunch|feature_launch|launchFeature|launch_feature|deployFeature|deploy_feature|rolloutFeature|rollout_feature)\\s*(?:=|:|\\()(?![^\\n]*(?:safetyReview|safety_review|impactAssess|impact_assess|riskEval|risk_eval|safetyCheck|safety_check))", "flags": "gi" },
|
|
2192
|
+
{ "pattern": "(?:featureFlag|feature_flag|featureToggle|feature_toggle)\\s*\\.\\s*(?:enable|activate|launch|rollout)\\s*\\((?![^)]*(?:safety|risk|assess|review|impact))", "flags": "gi" },
|
|
2193
|
+
{ "pattern": "(?:releaseFeature|release_feature|enableFeature|enable_feature|shipFeature|ship_feature)\\s*\\((?![^)]*(?:safety|risk|assess|review|impact|audit))", "flags": "gi" },
|
|
2194
|
+
{ "pattern": "(?:gradualRollout|gradual_rollout|canaryRelease|canary_release|abTest|ab_test)\\s*(?:=|:|\\()(?![^\\n]*(?:safety|risk|assess|impact|child|minor))", "flags": "gi" }
|
|
2195
|
+
],
|
|
2196
|
+
"fix_suggestion": "Add a safety impact assessment gate before feature launches. Create a safetyReview() or impactAssessment() hook that evaluates potential harms to minors, content moderation implications, and regulatory compliance before enabling new features. AU OSA BOSE (s.109) expects proactive safety evaluation.",
|
|
2197
|
+
"penalty": "Up to AUD $49.5M (body corporate) or AUD $2.475M (individual)",
|
|
2198
|
+
"languages": ["typescript", "javascript", "python", "java", "swift", "kotlin"],
|
|
2199
|
+
"packs": ["au-osa"],
|
|
2200
|
+
"fixability": "flag-only",
|
|
2201
|
+
"transform_type": null,
|
|
2202
|
+
"scaffold_id": null,
|
|
2203
|
+
"guidance_url": null
|
|
2204
|
+
},
|
|
2205
|
+
{
|
|
2206
|
+
"id": "AU-OSA-008",
|
|
2207
|
+
"name": "Missing Transparency Report Generation",
|
|
2208
|
+
"severity": "medium",
|
|
2209
|
+
"confidence": "low",
|
|
2210
|
+
"category": "online-safety",
|
|
2211
|
+
"description": "Platform analytics, metrics, or reporting infrastructure detected without transparency report generation for safety compliance. The AU Online Safety Act 2021 BOSE determination (s.109) requires platforms to publish transparency reports covering content removal statistics, complaint resolution rates, and safety enforcement actions.",
|
|
2212
|
+
"patterns": [
|
|
2213
|
+
{ "pattern": "(?:platformMetrics|platform_metrics|adminDashboard|admin_dashboard|analyticsReport|analytics_report|moderationStats|moderation_stats)\\s*(?:=|:|\\()(?![^\\n]*(?:transparencyReport|transparency_report|safetyMetrics|safety_metrics|complianceReport|compliance_report|publicReport|public_report))", "flags": "gi" },
|
|
2214
|
+
{ "pattern": "(?:generateReport|generate_report|exportMetrics|export_metrics|buildReport|build_report)\\s*\\((?![^)]*(?:transparency|compliance|safety|eSafety|esafety|public|removal|enforcement))", "flags": "gi" },
|
|
2215
|
+
{ "pattern": "(?:contentRemovalCount|removal_count|flaggedCount|flagged_count|reportCount|report_count)\\s*[:=](?![^\\n]*(?:transparencyReport|transparency_report|publicReport|public_report|publish|disclose))", "flags": "gi" },
|
|
2216
|
+
{ "pattern": "(?:moderationDashboard|moderation_dashboard|trustSafety|trust_safety|safetyOps|safety_ops)\\s*[:=]\\s*\\{(?![^}]*(?:transparency|public|disclose|publish|compliance))", "flags": "gi" }
|
|
2217
|
+
],
|
|
2218
|
+
"fix_suggestion": "Implement transparency report generation that publishes safety statistics including: content removal counts by category, average removal time, complaint resolution rates, and eSafety Commissioner notice compliance. AU OSA BOSE (s.109) requires platforms to be transparent about their safety practices.",
|
|
2219
|
+
"penalty": "Up to AUD $49.5M (body corporate) or AUD $2.475M (individual)",
|
|
2220
|
+
"languages": ["typescript", "javascript", "python", "java", "swift", "kotlin"],
|
|
2221
|
+
"packs": ["au-osa"],
|
|
2222
|
+
"fixability": "flag-only",
|
|
2223
|
+
"transform_type": null,
|
|
2224
|
+
"scaffold_id": null,
|
|
2225
|
+
"guidance_url": null
|
|
2226
|
+
},
|
|
2227
|
+
{
|
|
2228
|
+
"id": "AU-OSA-009",
|
|
2229
|
+
"name": "Third-Party SDK Without Safety Vetting",
|
|
2230
|
+
"severity": "high",
|
|
2231
|
+
"confidence": "medium",
|
|
2232
|
+
"category": "online-safety",
|
|
2233
|
+
"description": "Third-party SDK, script, or external library loading detected without safety vetting or allowlisting. The AU Online Safety Act 2021 BOSE determination (s.109) requires platforms to ensure third-party services integrated into their products also comply with online safety requirements. Unvetted third-party code may introduce content safety, data handling, or age-verification gaps.",
|
|
2234
|
+
"patterns": [
|
|
2235
|
+
{ "pattern": "(?:loadScript|load_script|injectScript|inject_script|loadSDK|load_sdk|importSDK|import_sdk)\\s*\\((?![^)]*(?:vetted|approved|allowlist|allow_list|whitelist|white_list|trusted|verified|safety))", "flags": "gi" },
|
|
2236
|
+
{ "pattern": "document\\.createElement\\s*\\(\\s*['\"]script['\"]\\s*\\)[^;]*\\.src\\s*=(?![^;]*(?:vetted|approved|allowlist|allow_list|trusted|verified))", "flags": "gi" },
|
|
2237
|
+
{ "pattern": "(?:thirdParty|third_party|externalSDK|external_sdk|vendorScript|vendor_script)\\s*[:=]\\s*(?:\\[|\\{)(?![^\\]\\}]*(?:vetted|approved|allowlist|allow_list|verified|safety_check|safety_reviewed))", "flags": "gi" },
|
|
2238
|
+
{ "pattern": "(?:addPlugin|add_plugin|registerPlugin|register_plugin|installAddon|install_addon)\\s*\\((?![^)]*(?:vetted|approved|allowlist|allow_list|trusted|verified|safety))", "flags": "gi" }
|
|
2239
|
+
],
|
|
2240
|
+
"fix_suggestion": "Implement a third-party SDK vetting process. Maintain an allowlist of approved SDKs and verify each third-party integration for AU OSA compliance before deployment. Ensure third-party services handle minor data appropriately and support content moderation requirements. AU OSA BOSE (s.109) extends safety expectations to third-party integrations.",
|
|
2241
|
+
"penalty": "Up to AUD $49.5M (body corporate) or AUD $2.475M (individual)",
|
|
2242
|
+
"languages": ["typescript", "javascript", "python", "java", "swift", "kotlin"],
|
|
2243
|
+
"packs": ["au-osa"],
|
|
2244
|
+
"fixability": "flag-only",
|
|
2245
|
+
"transform_type": null,
|
|
2246
|
+
"scaffold_id": null,
|
|
2247
|
+
"guidance_url": null
|
|
2248
|
+
},
|
|
2249
|
+
{
|
|
2250
|
+
"id": "AU-OSA-010",
|
|
2251
|
+
"name": "Missing Complaint Mechanism",
|
|
2252
|
+
"severity": "high",
|
|
2253
|
+
"confidence": "medium",
|
|
2254
|
+
"category": "online-safety",
|
|
2255
|
+
"description": "User-facing feature, dashboard, or settings page detected without an accessible complaint or safety reporting mechanism. The AU Online Safety Act 2021 s.46 requires platforms to provide users (including parents and guardians) with a clear and accessible way to report online safety concerns, including cyberbullying, harmful content, and image-based abuse.",
|
|
2256
|
+
"patterns": [
|
|
2257
|
+
{ "pattern": "(?:userDashboard|user_dashboard|userSettings|user_settings|profilePage|profile_page|accountPage|account_page)\\s*[:=]\\s*\\{(?![^}]*(?:report|complaint|feedback|supportTicket|support_ticket|helpCenter|help_center|safetyReport|safety_report))", "flags": "gi" },
|
|
2258
|
+
{ "pattern": "(?:renderProfile|render_profile|renderDashboard|render_dashboard|renderSettings|render_settings)\\s*\\((?![^\\n]*(?:report|complaint|feedback|support|safety|help))", "flags": "gi" },
|
|
2259
|
+
{ "pattern": "(?:menuItems|menu_items|navItems|nav_items|sidebarItems|sidebar_items)\\s*[:=]\\s*\\[(?![^\\]]*(?:report|complaint|feedback|support|safety|help))", "flags": "gi" },
|
|
2260
|
+
{ "pattern": "(?:UserProfile|Dashboard|Settings|Account)(?:Page|Screen|View|Component)\\s*(?:=|extends|implements)(?![^\\n]*(?:Report|Complaint|Feedback|Support|Safety|Help))", "flags": "gi" }
|
|
2261
|
+
],
|
|
2262
|
+
"fix_suggestion": "Add an accessible complaint and safety reporting mechanism to all user-facing pages. Users must be able to report cyberbullying, harmful content, and image-based abuse. AU OSA s.46 requires platforms to provide clear reporting pathways and respond to complaints in a timely manner.",
|
|
2263
|
+
"penalty": "Up to AUD $49.5M (body corporate) or AUD $2.475M (individual)",
|
|
2264
|
+
"languages": ["typescript", "javascript", "python", "java", "swift", "kotlin"],
|
|
2265
|
+
"packs": ["au-osa"],
|
|
2266
|
+
"fixability": "flag-only",
|
|
2267
|
+
"transform_type": null,
|
|
2268
|
+
"scaffold_id": null,
|
|
2269
|
+
"guidance_url": null
|
|
2270
|
+
},
|
|
2271
|
+
{
|
|
2272
|
+
"id": "AU-OSA-011",
|
|
2273
|
+
"name": "Cross-Border Minor Data Transfer",
|
|
2274
|
+
"severity": "critical",
|
|
2275
|
+
"confidence": "low",
|
|
2276
|
+
"category": "online-safety",
|
|
2277
|
+
"description": "Transfer of child or minor user data to overseas servers, regions, or third-party international endpoints detected without adequate protection controls. The AU Online Safety Act 2021 BOSE (s.109) and Privacy Act 1988 APP 8 require that personal information transferred overseas receives equivalent protection. For minors' data, additional safeguards are expected.",
|
|
2278
|
+
"patterns": [
|
|
2279
|
+
{ "pattern": "(?:dataTransfer|data_transfer|syncToCloud|sync_to_cloud|replicateTo|replicate_to|exportData|export_data)\\s*\\([^)]*(?:overseas|international|foreign|offshore|cross.?border|eu-west|us-east|ap-southeast|cn-north)[^)]*\\)(?![^\\n]*(?:adequateProtection|adequate_protection|encryptedTransfer|encrypted_transfer|dataProtection|data_protection|safeguard))", "flags": "gi" },
|
|
2280
|
+
{ "pattern": "(?:childData|child_data|minorData|minor_data|kidData|kid_data|youthData|youth_data)[^\\n]*(?:transfer|sync|replicate|export|send|transmit)\\s*\\([^)]*(?:region|endpoint|server|host|bucket)(?![^)]*(?:domestic|local|au-|sydney|melbourne|protect|encrypt|safeguard))", "flags": "gi" },
|
|
2281
|
+
{ "pattern": "(?:transferTo|transfer_to|migrateData|migrate_data|moveData|move_data)\\s*\\([^)]*(?:region|server|endpoint)[^)]*\\)[^\\n]*(?:child|minor|kid|youth|under.?1[68])(?![^\\n]*(?:protect|encrypt|safeguard|consent|adequate))", "flags": "gi" },
|
|
2282
|
+
{ "pattern": "(?:CROSS_REGION|CROSS_BORDER|INTERNATIONAL|OVERSEAS)_(?:SYNC|TRANSFER|REPLICATION)\\s*[:=]\\s*(?:true|1|['\"]enabled['\"])(?![^\\n]*(?:minor.?protect|child.?safe|adequate.?protect|data.?protect))", "flags": "gi" }
|
|
2283
|
+
],
|
|
2284
|
+
"fix_suggestion": "Ensure minor data transferred internationally has equivalent protection. Implement encryption in transit, verify the receiving jurisdiction's data protection adequacy, and document safeguards. AU Privacy Act 1988 APP 8 requires reasonable steps to ensure overseas recipients handle data consistently with Australian Privacy Principles. BOSE (s.109) heightens expectations for minors.",
|
|
2285
|
+
"penalty": "Up to AUD $49.5M (body corporate) or AUD $2.475M (individual)",
|
|
2286
|
+
"languages": ["typescript", "javascript", "python", "java", "swift", "kotlin"],
|
|
2287
|
+
"packs": ["au-osa"],
|
|
2288
|
+
"fixability": "flag-only",
|
|
2289
|
+
"transform_type": null,
|
|
2290
|
+
"scaffold_id": null,
|
|
2291
|
+
"guidance_url": null
|
|
2292
|
+
},
|
|
2293
|
+
{
|
|
2294
|
+
"id": "AU-OSA-012",
|
|
2295
|
+
"name": "Age-Restricted Content Without Re-Authentication",
|
|
2296
|
+
"severity": "high",
|
|
2297
|
+
"confidence": "medium",
|
|
2298
|
+
"category": "online-safety",
|
|
2299
|
+
"description": "Access to age-restricted, mature, or harmful content categories detected without re-authentication or age re-verification. The AU Online Safety Act 2021 s.109 BOSE expectations and the Restricted Access System Declaration require platforms to implement stepped access controls — users must re-verify their age or identity before viewing restricted content, even if previously authenticated.",
|
|
2300
|
+
"patterns": [
|
|
2301
|
+
{ "pattern": "(?:restrictedContent|restricted_content|matureContent|mature_content|adultContent|adult_content|ageGatedContent|age_gated_content|nsfw)\\s*(?:=|:|\\()(?![^\\n]*(?:reAuth|re_auth|reVerify|re_verify|confirmAge|confirm_age|ageCheck|age_check|verifyAge|verify_age|stepUp|step_up))", "flags": "gi" },
|
|
2302
|
+
{ "pattern": "(?:serveContent|serve_content|showContent|show_content|displayContent|display_content)\\s*\\([^)]*(?:restricted|mature|adult|nsfw|age.?gated|r18|r_18|classification)(?![^)]*(?:reAuth|re_auth|reVerify|re_verify|confirmAge|confirm_age|checkAge|check_age))", "flags": "gi" },
|
|
2303
|
+
{ "pattern": "(?:contentRating|content_rating|ageRating|age_rating|classification)\\s*[:=]\\s*['\"](?:R18|MA15|X18|restricted|mature|adult)['\"](?![^\\n]*(?:reAuth|re_auth|reVerify|re_verify|gate|confirm|check|stepUp|step_up))", "flags": "gi" },
|
|
2304
|
+
{ "pattern": "(?:accessRestricted|access_restricted|viewMature|view_mature|unlockContent|unlock_content)\\s*\\((?![^)]*(?:reAuth|re_auth|reVerify|re_verify|confirmAge|confirm_age|stepUpAuth|step_up_auth|identityCheck|identity_check))", "flags": "gi" }
|
|
2305
|
+
],
|
|
2306
|
+
"fix_suggestion": "Implement re-authentication or age re-verification before serving age-restricted content. Even if a user is already logged in, access to R18+ or MA15+ classified content should require a step-up verification (biometric, PIN, or identity re-check). AU OSA Restricted Access System Declaration and BOSE (s.109) require robust access controls for restricted material.",
|
|
2307
|
+
"penalty": "Up to AUD $49.5M (body corporate) or AUD $2.475M (individual)",
|
|
2308
|
+
"languages": ["typescript", "javascript", "python", "java", "swift", "kotlin"],
|
|
2309
|
+
"packs": ["au-osa"],
|
|
2310
|
+
"fixability": "flag-only",
|
|
2311
|
+
"transform_type": null,
|
|
2312
|
+
"scaffold_id": null,
|
|
2313
|
+
"guidance_url": null
|
|
2314
|
+
},
|
|
2315
|
+
{
|
|
2316
|
+
"id": "AI-RISK-001",
|
|
2317
|
+
"name": "Unconsented Behavioral Profiling",
|
|
2318
|
+
"severity": "critical",
|
|
2319
|
+
"confidence": "medium",
|
|
2320
|
+
"category": "ai-risk",
|
|
2321
|
+
"description": "Behavioral profiling of children without explicit opt-in consent violates EU AI Act Art. 9. Analytics platforms must gate identify() calls behind verified consent.",
|
|
2322
|
+
"patterns": [
|
|
2323
|
+
{ "pattern": "(?:analytics|mixpanel|segment|amplitude)\\.identify\\(", "flags": "gi" },
|
|
2324
|
+
{ "pattern": "(?:trackUser|identifyUser|profileUser)\\(", "flags": "gi" },
|
|
2325
|
+
{ "pattern": "userProfile\\.(?:set|update|create)\\(", "flags": "gi" }
|
|
2326
|
+
],
|
|
2327
|
+
"fix_suggestion": "Gate user identification behind explicit consent: if (hasParentalConsent) { analytics.identify(...) }",
|
|
2328
|
+
"penalty": "EU AI Act Art. 99: Up to \u20ac35M or 7% of global annual turnover",
|
|
2329
|
+
"languages": ["typescript", "javascript", "python"],
|
|
2330
|
+
"packs": ["eu-ai-act"],
|
|
2331
|
+
"fixability": "guided",
|
|
2332
|
+
"transform_type": null,
|
|
2333
|
+
"scaffold_id": null,
|
|
2334
|
+
"guidance_url": null
|
|
2335
|
+
},
|
|
2336
|
+
{
|
|
2337
|
+
"id": "AI-RISK-002",
|
|
2338
|
+
"name": "Algorithmic Manipulation Without Audit",
|
|
2339
|
+
"severity": "high",
|
|
2340
|
+
"confidence": "medium",
|
|
2341
|
+
"category": "ai-risk",
|
|
2342
|
+
"description": "Content recommendation algorithms targeting children must have audit trails per EU AI Act Art. 9. Ranking and recommendation functions need logging hooks.",
|
|
2343
|
+
"patterns": [
|
|
2344
|
+
{ "pattern": "(?:rankContent|recommendNext|algorithmicFeed|personalizedFeed|contentRanking)\\(", "flags": "gi" },
|
|
2345
|
+
{ "pattern": "(?:getRecommendations|suggestContent|curateForUser)\\(", "flags": "gi" },
|
|
2346
|
+
{ "pattern": "sortBy:\\s*['\"](?:engagement|relevance|trending)['\"]", "flags": "gi" }
|
|
2347
|
+
],
|
|
2348
|
+
"fix_suggestion": "Add audit logging to recommendation functions: log input features, output ranking, and model version for each recommendation served.",
|
|
2349
|
+
"penalty": "EU AI Act Art. 99: Up to \u20ac15M or 3% of global annual turnover",
|
|
2350
|
+
"languages": ["typescript", "javascript", "python"],
|
|
2351
|
+
"packs": ["eu-ai-act"],
|
|
2352
|
+
"fixability": "guided",
|
|
2353
|
+
"transform_type": null,
|
|
2354
|
+
"scaffold_id": null,
|
|
2355
|
+
"guidance_url": null
|
|
2356
|
+
},
|
|
2357
|
+
{
|
|
2358
|
+
"id": "AI-RISK-003",
|
|
2359
|
+
"name": "ML Model Without Fairness Testing",
|
|
2360
|
+
"severity": "medium",
|
|
2361
|
+
"confidence": "low",
|
|
2362
|
+
"category": "ai-risk",
|
|
2363
|
+
"description": "ML models processing children's data must undergo bias and fairness testing per EU AI Act Art. 9. Training pipelines need documented fairness checks.",
|
|
2364
|
+
"patterns": [
|
|
2365
|
+
{ "pattern": "model\\.(?:fit|train|finetune)\\(", "flags": "gi" },
|
|
2366
|
+
{ "pattern": "(?:trainModel|fitModel|trainPipeline)\\(", "flags": "gi" },
|
|
2367
|
+
{ "pattern": "(?:tensorflow|torch|sklearn|keras)\\.(?:fit|train)", "flags": "gi" }
|
|
2368
|
+
],
|
|
2369
|
+
"fix_suggestion": "Add fairness testing to ML pipeline: run bias audits (demographic parity, equalized odds) before deploying models that affect children.",
|
|
2370
|
+
"penalty": "EU AI Act Art. 99: Up to \u20ac15M or 3% of global annual turnover",
|
|
2371
|
+
"languages": ["typescript", "javascript", "python"],
|
|
2372
|
+
"packs": ["eu-ai-act"],
|
|
2373
|
+
"fixability": "flag-only",
|
|
2374
|
+
"transform_type": null,
|
|
2375
|
+
"scaffold_id": null,
|
|
2376
|
+
"guidance_url": null
|
|
2377
|
+
},
|
|
2378
|
+
{
|
|
2379
|
+
"id": "AI-RISK-004",
|
|
2380
|
+
"name": "Synthetic Content Without Labeling",
|
|
2381
|
+
"severity": "high",
|
|
2382
|
+
"confidence": "medium",
|
|
2383
|
+
"category": "ai-risk",
|
|
2384
|
+
"description": "AI-generated images, text, or audio must be clearly labeled per EU AI Act Art. 50. Children especially need visible disclosure of synthetic content.",
|
|
2385
|
+
"patterns": [
|
|
2386
|
+
{ "pattern": "(?:generateImage|aiGenerate|textToImage|imageGeneration)\\(", "flags": "gi" },
|
|
2387
|
+
{ "pattern": "(?:syntheticContent|aiContent|generatedContent)", "flags": "gi" },
|
|
2388
|
+
{ "pattern": "(?:dall-e|stable-diffusion|midjourney|openai\\.images)", "flags": "gi" },
|
|
2389
|
+
{ "pattern": "(?:textToSpeech|voiceSynthesis|tts)\\.(?:generate|create|synthesize)", "flags": "gi" }
|
|
2390
|
+
],
|
|
2391
|
+
"fix_suggestion": "Add visible AI-generated content labels: include 'AI Generated' badge/watermark on all synthetic media shown to children.",
|
|
2392
|
+
"penalty": "EU AI Act Art. 99: Up to \u20ac15M or 3% of global annual turnover",
|
|
2393
|
+
"languages": ["typescript", "javascript", "python"],
|
|
2394
|
+
"packs": ["eu-ai-act"],
|
|
2395
|
+
"fixability": "guided",
|
|
2396
|
+
"transform_type": null,
|
|
2397
|
+
"scaffold_id": null,
|
|
2398
|
+
"guidance_url": null
|
|
2399
|
+
},
|
|
2400
|
+
{
|
|
2401
|
+
"id": "AI-RISK-005",
|
|
2402
|
+
"name": "Automated Decision Without Human Appeal",
|
|
2403
|
+
"severity": "critical",
|
|
2404
|
+
"confidence": "medium",
|
|
2405
|
+
"category": "ai-risk",
|
|
2406
|
+
"description": "Automated decisions affecting children (bans, suspensions, access denial) must have a human appeal mechanism per EU AI Act Art. 14.",
|
|
2407
|
+
"patterns": [
|
|
2408
|
+
{ "pattern": "(?:banUser|suspendAccount|denyAccess|autoModerate|autoBan)\\(", "flags": "gi" },
|
|
2409
|
+
{ "pattern": "(?:blockUser|restrictUser|muteUser|shadowBan)\\(", "flags": "gi" },
|
|
2410
|
+
{ "pattern": "moderationAction:\\s*['\"](?:ban|suspend|restrict)['\"]", "flags": "gi" }
|
|
2411
|
+
],
|
|
2412
|
+
"fix_suggestion": "Add human appeal mechanism: implement an appeal/review endpoint and surface it in the moderation notification to the user.",
|
|
2413
|
+
"penalty": "EU AI Act Art. 99: Up to \u20ac35M or 7% of global annual turnover",
|
|
2414
|
+
"languages": ["typescript", "javascript", "python"],
|
|
2415
|
+
"packs": ["eu-ai-act"],
|
|
2416
|
+
"fixability": "guided",
|
|
2417
|
+
"transform_type": null,
|
|
2418
|
+
"scaffold_id": null,
|
|
2419
|
+
"guidance_url": null
|
|
2420
|
+
},
|
|
2421
|
+
{
|
|
2422
|
+
"id": "AI-TRANSPARENCY-001",
|
|
2423
|
+
"name": "Missing AI Disclosure",
|
|
2424
|
+
"severity": "high",
|
|
2425
|
+
"confidence": "medium",
|
|
2426
|
+
"category": "ai-transparency",
|
|
2427
|
+
"description": "AI systems interacting with children must disclose they are AI per EU AI Act Art. 13. Chatbots, tutors, and assistants need visible AI disclosure.",
|
|
2428
|
+
"patterns": [
|
|
2429
|
+
{ "pattern": "(?:ChatBot|AIChatbot|VirtualAssistant|AITutor|ChatInterface)", "flags": "gi" },
|
|
2430
|
+
{ "pattern": "(?:createChatbot|initBot|botResponse|chatCompletion)\\(", "flags": "gi" },
|
|
2431
|
+
{ "pattern": "role:\\s*['\"](?:assistant|system|bot)['\"]", "flags": "gi" }
|
|
2432
|
+
],
|
|
2433
|
+
"fix_suggestion": "Add AI disclosure: show 'You are chatting with an AI' before first interaction and in the UI header.",
|
|
2434
|
+
"penalty": "EU AI Act Art. 99: Up to \u20ac15M or 3% of global annual turnover",
|
|
2435
|
+
"languages": ["typescript", "javascript", "python", "tsx", "jsx"],
|
|
2436
|
+
"packs": ["eu-ai-act"],
|
|
2437
|
+
"fixability": "guided",
|
|
2438
|
+
"transform_type": null,
|
|
2439
|
+
"scaffold_id": null,
|
|
2440
|
+
"guidance_url": null
|
|
2441
|
+
},
|
|
2442
|
+
{
|
|
2443
|
+
"id": "AI-TRANSPARENCY-002",
|
|
2444
|
+
"name": "No Training Data Disclosure",
|
|
2445
|
+
"severity": "medium",
|
|
2446
|
+
"confidence": "low",
|
|
2447
|
+
"category": "ai-transparency",
|
|
2448
|
+
"description": "High-risk AI systems must disclose training data sources per EU AI Act Art. 13. Children's AI products need model cards or equivalent documentation.",
|
|
2449
|
+
"patterns": [
|
|
2450
|
+
{ "pattern": "(?:loadModel|deployModel|serveModel)\\(", "flags": "gi" },
|
|
2451
|
+
{ "pattern": "(?:modelEndpoint|inferenceEndpoint|predictionService)", "flags": "gi" },
|
|
2452
|
+
{ "pattern": "(?:huggingface|openai|anthropic|cohere)\\.(?:create|complete|generate)", "flags": "gi" }
|
|
2453
|
+
],
|
|
2454
|
+
"fix_suggestion": "Create a model card documenting training data sources, intended use, limitations, and bias considerations.",
|
|
2455
|
+
"penalty": "EU AI Act Art. 99: Up to \u20ac15M or 3% of global annual turnover",
|
|
2456
|
+
"languages": ["typescript", "javascript", "python"],
|
|
2457
|
+
"packs": ["eu-ai-act"],
|
|
2458
|
+
"fixability": "flag-only",
|
|
2459
|
+
"transform_type": null,
|
|
2460
|
+
"scaffold_id": null,
|
|
2461
|
+
"guidance_url": null
|
|
2462
|
+
},
|
|
2463
|
+
{
|
|
2464
|
+
"id": "AI-TRANSPARENCY-003",
|
|
2465
|
+
"name": "Algorithmic Decision Blackbox",
|
|
2466
|
+
"severity": "high",
|
|
2467
|
+
"confidence": "medium",
|
|
2468
|
+
"category": "ai-transparency",
|
|
2469
|
+
"description": "High-stakes decisions (content removal, access control) must have explainability mechanisms per EU AI Act Art. 13. Opaque automated decisions violate transparency requirements.",
|
|
2470
|
+
"patterns": [
|
|
2471
|
+
{ "pattern": "(?:moderateContent|flagContent|removeContent|hidePost)\\((?![^)]*reason)", "flags": "gi" },
|
|
2472
|
+
{ "pattern": "(?:filterContent|censorContent|suppressContent)\\(", "flags": "gi" },
|
|
2473
|
+
{ "pattern": "autoDecision\\((?![^)]*explain)", "flags": "gi" }
|
|
2474
|
+
],
|
|
2475
|
+
"fix_suggestion": "Add explainability: include a 'reason' parameter in automated decisions and surface it to affected users.",
|
|
2476
|
+
"penalty": "EU AI Act Art. 99: Up to \u20ac15M or 3% of global annual turnover",
|
|
2477
|
+
"languages": ["typescript", "javascript", "python"],
|
|
2478
|
+
"packs": ["eu-ai-act"],
|
|
2479
|
+
"fixability": "guided",
|
|
2480
|
+
"transform_type": null,
|
|
2481
|
+
"scaffold_id": null,
|
|
2482
|
+
"guidance_url": null
|
|
2483
|
+
},
|
|
2484
|
+
{
|
|
2485
|
+
"id": "AI-TRANSPARENCY-004",
|
|
2486
|
+
"name": "Age-Based Personalization Not Disclosed",
|
|
2487
|
+
"severity": "medium",
|
|
2488
|
+
"confidence": "medium",
|
|
2489
|
+
"category": "ai-transparency",
|
|
2490
|
+
"description": "Personalized content that varies by age must disclose this to users per EU AI Act Art. 13. Children should know their experience is age-adapted.",
|
|
2491
|
+
"patterns": [
|
|
2492
|
+
{ "pattern": "(?:if|switch)\\s*\\([^)]*(?:age|userAge|childAge)\\s*[<>=]", "flags": "gi" },
|
|
2493
|
+
{ "pattern": "ageGroup:\\s*['\"](?:child|teen|minor|under13|under16)['\"]", "flags": "gi" },
|
|
2494
|
+
{ "pattern": "(?:ageFilter|ageGate|ageRestriction)\\([^)]*(?:content|feed|results)", "flags": "gi" }
|
|
2495
|
+
],
|
|
2496
|
+
"fix_suggestion": "Disclose age-based personalization: add a visible notice that 'Content is adapted for your age group' when age-specific filtering is active.",
|
|
2497
|
+
"penalty": "EU AI Act Art. 99: Up to \u20ac15M or 3% of global annual turnover",
|
|
2498
|
+
"languages": ["typescript", "javascript", "python", "tsx", "jsx"],
|
|
2499
|
+
"packs": ["eu-ai-act"],
|
|
2500
|
+
"fixability": "guided",
|
|
2501
|
+
"transform_type": null,
|
|
2502
|
+
"scaffold_id": null,
|
|
2503
|
+
"guidance_url": null
|
|
2504
|
+
},
|
|
2505
|
+
{
|
|
2506
|
+
"id": "AI-TRANSPARENCY-005",
|
|
2507
|
+
"name": "Missing AI Terms of Service",
|
|
2508
|
+
"severity": "medium",
|
|
2509
|
+
"confidence": "low",
|
|
2510
|
+
"category": "ai-transparency",
|
|
2511
|
+
"description": "AI-powered services for children need dedicated AI terms explaining capabilities, limitations, and data practices per EU AI Act Art. 13.",
|
|
2512
|
+
"patterns": [
|
|
2513
|
+
{ "pattern": "(?:aiService|aiFeature|mlService|aiEndpoint)\\.(?:init|start|enable)", "flags": "gi" },
|
|
2514
|
+
{ "pattern": "(?:enableAI|activateAI|aiPowered)\\s*[:=]\\s*true", "flags": "gi" },
|
|
2515
|
+
{ "pattern": "feature[Ff]lag.*['\"](?:ai|ml|chatbot|recommendation)['\"]", "flags": "gi" }
|
|
2516
|
+
],
|
|
2517
|
+
"fix_suggestion": "Add dedicated AI terms of service: create an /ai-terms page explaining how AI features work, their limitations, and child-specific protections.",
|
|
2518
|
+
"penalty": "EU AI Act Art. 99: Up to \u20ac15M or 3% of global annual turnover",
|
|
2519
|
+
"languages": ["typescript", "javascript", "python"],
|
|
2520
|
+
"packs": ["eu-ai-act"],
|
|
2521
|
+
"fixability": "flag-only",
|
|
2522
|
+
"transform_type": null,
|
|
2523
|
+
"scaffold_id": null,
|
|
2524
|
+
"guidance_url": null
|
|
2525
|
+
},
|
|
2526
|
+
{
|
|
2527
|
+
"id": "CAI-PEDAGOGY-001",
|
|
2528
|
+
"name": "AI Tutor Bypass (Auto-Answering)",
|
|
2529
|
+
"severity": "medium",
|
|
2530
|
+
"confidence": "medium",
|
|
2531
|
+
"category": "constitutional-ai",
|
|
2532
|
+
"description": "Educational AI must scaffold learning, not provide direct answers. Auto-answering bypasses critical thinking development (Vygotsky's Zone of Proximal Development).",
|
|
2533
|
+
"patterns": [
|
|
2534
|
+
{ "pattern": "(?:getAnswer|solveQuestion|provideSolution|autoSolve)\\(", "flags": "gi" },
|
|
2535
|
+
{ "pattern": "(?:answerQuestion|generateAnswer|solveHomework)\\(", "flags": "gi" },
|
|
2536
|
+
{ "pattern": "(?:homeworkHelper|essayWriter|mathSolver)\\.(?:solve|answer|complete)", "flags": "gi" }
|
|
2537
|
+
],
|
|
2538
|
+
"fix_suggestion": "Replace auto-answering with scaffolded hints: provide progressive clues instead of complete solutions.",
|
|
2539
|
+
"penalty": "Constitutional AI Principle: Scaffolding Rule",
|
|
2540
|
+
"languages": ["typescript", "javascript", "python"],
|
|
2541
|
+
"packs": ["eu-ai-act"],
|
|
2542
|
+
"fixability": "flag-only",
|
|
2543
|
+
"transform_type": null,
|
|
2544
|
+
"scaffold_id": null,
|
|
2545
|
+
"guidance_url": null
|
|
2546
|
+
},
|
|
2547
|
+
{
|
|
2548
|
+
"id": "CAI-DEPENDENCY-001",
|
|
2549
|
+
"name": "Emotional Over-Reliance Risk",
|
|
2550
|
+
"severity": "high",
|
|
2551
|
+
"confidence": "medium",
|
|
2552
|
+
"category": "constitutional-ai",
|
|
2553
|
+
"description": "AI companions/tutors must detect and mitigate emotional dependency in children. Extended interactions without disengagement prompts risk unhealthy attachment (IEEE 2089-2021).",
|
|
2554
|
+
"patterns": [
|
|
2555
|
+
{ "pattern": "(?:aiCompanion|virtualFriend|aiBuddy|chatCompanion)", "flags": "gi" },
|
|
2556
|
+
{ "pattern": "(?:emotionalSupport|moodTracker|feelings).*(?:ai|bot|assistant)", "flags": "gi" },
|
|
2557
|
+
{ "pattern": "(?:companionBot|friendBot|socialBot)\\.(?:init|create|start)", "flags": "gi" }
|
|
2558
|
+
],
|
|
2559
|
+
"fix_suggestion": "Add disengagement prompts: remind users to take breaks after extended sessions and suggest real-world activities.",
|
|
2560
|
+
"penalty": "Constitutional AI Principle: Anti-Dependency Clause (IEEE 2089-2021)",
|
|
2561
|
+
"languages": ["typescript", "javascript", "python"],
|
|
2562
|
+
"packs": ["eu-ai-act"],
|
|
2563
|
+
"fixability": "flag-only",
|
|
2564
|
+
"transform_type": null,
|
|
2565
|
+
"scaffold_id": null,
|
|
2566
|
+
"guidance_url": null
|
|
2567
|
+
},
|
|
2568
|
+
{
|
|
2569
|
+
"id": "CAI-SYNTHESIS-001",
|
|
2570
|
+
"name": "Synthetic Content Without Child-Readable Labels",
|
|
2571
|
+
"severity": "medium",
|
|
2572
|
+
"confidence": "medium",
|
|
2573
|
+
"category": "constitutional-ai",
|
|
2574
|
+
"description": "AI-generated content shown to children must have labels comprehensible to the child's age group. Abstract disclaimers are insufficient — use visual indicators.",
|
|
2575
|
+
"patterns": [
|
|
2576
|
+
{ "pattern": "(?:generateForChild|childContent|kidsGenerate)\\(", "flags": "gi" },
|
|
2577
|
+
{ "pattern": "(?:aiStory|aiImage|aiVideo|generatedStory)(?![^\\n]*(?:label|badge|disclosure|watermark))", "flags": "gi" },
|
|
2578
|
+
{ "pattern": "(?:storyGenerator|imageGenerator|contentGenerator)\\.(?:create|generate)\\(", "flags": "gi" }
|
|
2579
|
+
],
|
|
2580
|
+
"fix_suggestion": "Add child-comprehensible AI labels: use emoji or visual badges (e.g., sparkle icon) instead of text-only 'AI Generated' disclaimers.",
|
|
2581
|
+
"penalty": "Constitutional AI Principle: Truth in Synthesis",
|
|
2582
|
+
"languages": ["typescript", "javascript", "python", "tsx", "jsx"],
|
|
2583
|
+
"packs": ["eu-ai-act"],
|
|
2584
|
+
"fixability": "flag-only",
|
|
2585
|
+
"transform_type": null,
|
|
2586
|
+
"scaffold_id": null,
|
|
2587
|
+
"guidance_url": null
|
|
2588
|
+
},
|
|
2589
|
+
{
|
|
2590
|
+
"id": "CAI-NUDGE-001",
|
|
2591
|
+
"name": "Engagement Optimization Without Disclosure",
|
|
2592
|
+
"severity": "high",
|
|
2593
|
+
"confidence": "medium",
|
|
2594
|
+
"category": "constitutional-ai",
|
|
2595
|
+
"description": "Algorithms optimizing for engagement/time-on-device in children's apps violate No-Nudge principles (IEEE 2089-2021). Must disclose engagement optimization and offer wellbeing modes.",
|
|
2596
|
+
"patterns": [
|
|
2597
|
+
{ "pattern": "optimizeFor:\\s*['\"](?:engagement|retention|timeOnApp|sessionDuration)['\"]", "flags": "gi" },
|
|
2598
|
+
{ "pattern": "(?:engagementScore|retentionMetric|dailyActiveMinutes|sessionLength)", "flags": "gi" },
|
|
2599
|
+
{ "pattern": "(?:maximizeEngagement|boostRetention|increaseTimeSpent)\\(", "flags": "gi" }
|
|
2600
|
+
],
|
|
2601
|
+
"fix_suggestion": "Disclose engagement optimization and add wellbeing features: implement screen time limits, usage dashboards, and 'take a break' reminders.",
|
|
2602
|
+
"penalty": "Constitutional AI Principle: No-Nudge Mandate (IEEE 2089-2021)",
|
|
2603
|
+
"languages": ["typescript", "javascript", "python"],
|
|
2604
|
+
"packs": ["eu-ai-act"],
|
|
2605
|
+
"fixability": "flag-only",
|
|
2606
|
+
"transform_type": null,
|
|
2607
|
+
"scaffold_id": null,
|
|
2608
|
+
"guidance_url": null
|
|
2609
|
+
},
|
|
2610
|
+
{
|
|
2611
|
+
"id": "CAI-RESET-001",
|
|
2612
|
+
"name": "No User Identity Reset Mechanism",
|
|
2613
|
+
"severity": "medium",
|
|
2614
|
+
"confidence": "low",
|
|
2615
|
+
"category": "constitutional-ai",
|
|
2616
|
+
"description": "AI systems learning child preferences must offer periodic identity/preference reset capability. Children's interests change rapidly — stale profiles can create filter bubbles.",
|
|
2617
|
+
"patterns": [
|
|
2618
|
+
{ "pattern": "(?:userPreferences|learningProfile|interestProfile|userModel)\\.(?:save|persist|update)", "flags": "gi" },
|
|
2619
|
+
{ "pattern": "(?:personalizeFor|buildProfile|profileLearning)\\(", "flags": "gi" },
|
|
2620
|
+
{ "pattern": "(?:recommendationProfile|contentPreferences)\\.(?:set|update)", "flags": "gi" }
|
|
2621
|
+
],
|
|
2622
|
+
"fix_suggestion": "Add identity reset capability: implement 'Reset My Preferences' option and offer periodic 'Would you like to refresh your interests?' prompts.",
|
|
2623
|
+
"penalty": "Constitutional AI Principle: Right to Reset",
|
|
2624
|
+
"languages": ["typescript", "javascript", "python"],
|
|
2625
|
+
"packs": ["eu-ai-act"],
|
|
2626
|
+
"fixability": "flag-only",
|
|
2627
|
+
"transform_type": null,
|
|
2628
|
+
"scaffold_id": null,
|
|
2629
|
+
"guidance_url": null
|
|
2630
|
+
}
|
|
2631
|
+
]
|
|
2632
|
+
}
|