Emily commited on
Commit
7bfe1af
·
1 Parent(s): 0cc3b61

Add comprehensive Privacy Attacks visualization page

Browse files

- Create new /attacks route with interactive privacy attack demonstrations
- Add 5 attack types: Membership Inference, Data Reconstruction, Model Inversion, Property Inference, and Linkage Attack
- Redesign Membership Inference with beginner-friendly story-based flow (no confusing numbered steps)
- Add interactive demos with real-time privacy parameter adjustments
- Include visual confidence comparisons and attack success rate indicators
- Add real-world examples and defense mechanism explanations
- Update navigation to include Privacy Attacks page before Learning Hub
- Add comprehensive CSS styling and JavaScript for interactive features

app/analytics.log.jsonl CHANGED
@@ -174,3 +174,8 @@
174
  {"t": 1757898352049, "sessionId": "e6fbeada-329d-41e3-aa40-155e0da60edb", "eventType": "ui_click", "path": "/learning", "payload": {"name": "Playground"}, "user": {}, "vid": "24e47deb0173460e8dd8a821f219efe9", "server_time": "2025-09-15T01:05:52.056017Z", "visitor_id": "a8e5594073f248f099de4e5497ddb0b4", "client_ip_truncated": "127.0.0.0", "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36", "referer": "http://127.0.0.1:5000/learning", "dnt": false, "gpc": false}
175
  {"t": 1757898431382, "sessionId": "e6fbeada-329d-41e3-aa40-155e0da60edb", "eventType": "ui_click", "path": "/", "payload": {"name": "Learning Hub"}, "user": {}, "vid": "e052efa6573a46f1bb059f505ada8544", "server_time": "2025-09-15T01:07:11.407601Z", "visitor_id": "6ae2cb63be1840929100920b940ae332", "client_ip_truncated": "127.0.0.0", "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36", "referer": "http://127.0.0.1:5000/", "dnt": false, "gpc": false}
176
  {"t": 1757898439032, "sessionId": "e6fbeada-329d-41e3-aa40-155e0da60edb", "eventType": "ui_click", "path": "/learning", "payload": {"name": "Playground"}, "user": {}, "vid": "287ddc28a4b24227a2076b5d34a49e6b", "server_time": "2025-09-15T01:07:19.037150Z", "visitor_id": "299e5e6dcaed47a990fc7c795739b3c3", "client_ip_truncated": "127.0.0.0", "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36", "referer": "http://127.0.0.1:5000/learning", "dnt": false, "gpc": false}
 
 
 
 
 
 
174
  {"t": 1757898352049, "sessionId": "e6fbeada-329d-41e3-aa40-155e0da60edb", "eventType": "ui_click", "path": "/learning", "payload": {"name": "Playground"}, "user": {}, "vid": "24e47deb0173460e8dd8a821f219efe9", "server_time": "2025-09-15T01:05:52.056017Z", "visitor_id": "a8e5594073f248f099de4e5497ddb0b4", "client_ip_truncated": "127.0.0.0", "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36", "referer": "http://127.0.0.1:5000/learning", "dnt": false, "gpc": false}
175
  {"t": 1757898431382, "sessionId": "e6fbeada-329d-41e3-aa40-155e0da60edb", "eventType": "ui_click", "path": "/", "payload": {"name": "Learning Hub"}, "user": {}, "vid": "e052efa6573a46f1bb059f505ada8544", "server_time": "2025-09-15T01:07:11.407601Z", "visitor_id": "6ae2cb63be1840929100920b940ae332", "client_ip_truncated": "127.0.0.0", "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36", "referer": "http://127.0.0.1:5000/", "dnt": false, "gpc": false}
176
  {"t": 1757898439032, "sessionId": "e6fbeada-329d-41e3-aa40-155e0da60edb", "eventType": "ui_click", "path": "/learning", "payload": {"name": "Playground"}, "user": {}, "vid": "287ddc28a4b24227a2076b5d34a49e6b", "server_time": "2025-09-15T01:07:19.037150Z", "visitor_id": "299e5e6dcaed47a990fc7c795739b3c3", "client_ip_truncated": "127.0.0.0", "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36", "referer": "http://127.0.0.1:5000/learning", "dnt": false, "gpc": false}
177
+ {"t": 1761774994565, "sessionId": "29052a4b-7a1c-4f5c-8e36-9d2b50e4c8de", "eventType": "ui_click", "path": "/", "payload": {"name": "Privacy Attacks"}, "user": {}, "vid": "2c5db8a6a7634b4a9d9a4bbe9ebb3c5e", "server_time": "2025-10-29T21:56:34.573200Z", "visitor_id": "c228c7f12d2d4c3ead765becb9033c59", "client_ip_truncated": "127.0.0.0", "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36", "referer": "http://127.0.0.1:5000/", "dnt": false, "gpc": false}
178
+ {"t": 1761775066392, "sessionId": "29052a4b-7a1c-4f5c-8e36-9d2b50e4c8de", "eventType": "ui_click", "path": "/attacks", "payload": {"name": "Run Attack"}, "user": {}, "vid": "539cbc63df294679bf0896d227154d34", "server_time": "2025-10-29T21:57:46.396352Z", "visitor_id": "104f7bb1325e4d00a803928450fe64b5", "client_ip_truncated": "127.0.0.0", "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36", "referer": "http://127.0.0.1:5000/attacks", "dnt": false, "gpc": false}
179
+ {"t": 1761775075784, "sessionId": "29052a4b-7a1c-4f5c-8e36-9d2b50e4c8de", "eventType": "ui_click", "path": "/attacks", "payload": {"name": "Data Reconstruction"}, "user": {}, "vid": "539cbc63df294679bf0896d227154d34", "server_time": "2025-10-29T21:57:55.787095Z", "visitor_id": "78f83018bf744464a9f5c6c4b7592f9b", "client_ip_truncated": "127.0.0.0", "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36", "referer": "http://127.0.0.1:5000/attacks", "dnt": false, "gpc": false}
180
+ {"t": 1761775244547, "sessionId": "29052a4b-7a1c-4f5c-8e36-9d2b50e4c8de", "eventType": "ui_click", "path": "/attacks", "payload": {"name": "Membership Inference"}, "user": {}, "vid": "539cbc63df294679bf0896d227154d34", "server_time": "2025-10-29T22:00:44.550688Z", "visitor_id": "fccadea4699a44878d739754ab550ce6", "client_ip_truncated": "127.0.0.0", "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36", "referer": "http://127.0.0.1:5000/attacks", "dnt": false, "gpc": false}
181
+ {"t": 1761775654300, "sessionId": "17617756460465c10c07bc70e", "eventType": "ui_click", "path": "/", "payload": {"name": "Privacy Attacks"}, "user": {}, "vid": "69e1b401114b49fc822a08f11d3e5622", "server_time": "2025-10-29T22:07:34.307770Z", "visitor_id": "afea81103d01464694ace5666287fb3f", "client_ip_truncated": "172.16.85.0", "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36", "referer": "http://172.16.85.236:7860/", "dnt": false, "gpc": false}
app/routes.py CHANGED
@@ -53,6 +53,10 @@ def get_or_create_trainer(dataset, model_architecture='simple-mlp'):
53
  def index():
54
  return render_template('index.html')
55
 
 
 
 
 
56
  @main.route('/learning')
57
  def learning():
58
  return render_template('learning.html')
@@ -177,6 +181,77 @@ def trainer_status():
177
  'dataset': 'MNIST' if REAL_TRAINER_AVAILABLE else 'synthetic'
178
  })
179
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
 
181
  # ===== Analytics & Identity Endpoints =====
182
  COOKIE_NAME = "vid"
 
53
  def index():
54
  return render_template('index.html')
55
 
56
+ @main.route('/attacks')
57
+ def attacks():
58
+ return render_template('attacks.html')
59
+
60
  @main.route('/learning')
61
  def learning():
62
  return render_template('learning.html')
 
181
  'dataset': 'MNIST' if REAL_TRAINER_AVAILABLE else 'synthetic'
182
  })
183
 
184
+ @main.route('/api/attack-simulation', methods=['POST', 'OPTIONS'])
185
+ @cross_origin()
186
+ def simulate_attack():
187
+ """Simulate privacy attacks with given parameters."""
188
+ if request.method == 'OPTIONS':
189
+ return jsonify({'status': 'ok'})
190
+
191
+ try:
192
+ data = request.json
193
+ if not data:
194
+ return jsonify({'error': 'No data provided'}), 400
195
+
196
+ attack_type = data.get('attack_type')
197
+ epsilon = float(data.get('epsilon', 3.0))
198
+ noise_multiplier = float(data.get('noise_multiplier', 1.0))
199
+
200
+ # Simulate different attack success rates based on privacy parameters
201
+ if attack_type == 'membership_inference':
202
+ # Membership inference attack simulation
203
+ base_success = 87 # No privacy baseline
204
+ privacy_reduction = max(0, (10 - epsilon) * 3.5)
205
+ noise_reduction = (noise_multiplier - 0.1) * 8
206
+ success_rate = max(50, min(95, base_success - privacy_reduction - noise_reduction))
207
+
208
+ return jsonify({
209
+ 'attack_type': 'membership_inference',
210
+ 'success_rate': round(success_rate, 1),
211
+ 'epsilon': epsilon,
212
+ 'noise_multiplier': noise_multiplier,
213
+ 'privacy_level': 'high' if epsilon < 2 else 'medium' if epsilon < 5 else 'low'
214
+ })
215
+
216
+ elif attack_type == 'data_reconstruction':
217
+ # Data reconstruction attack simulation
218
+ clipping_norm = float(data.get('clipping_norm', 1.0))
219
+ base_quality = 0.95
220
+ clipping_reduction = (5 - clipping_norm) * 0.1
221
+ noise_reduction = noise_multiplier * 0.25
222
+ quality = max(0.1, base_quality - clipping_reduction - noise_reduction)
223
+
224
+ return jsonify({
225
+ 'attack_type': 'data_reconstruction',
226
+ 'reconstruction_quality': round(quality, 3),
227
+ 'epsilon': epsilon,
228
+ 'noise_multiplier': noise_multiplier,
229
+ 'clipping_norm': clipping_norm
230
+ })
231
+
232
+ elif attack_type == 'linkage_attack':
233
+ # Linkage attack simulation
234
+ aux_data_quality = int(data.get('aux_data_quality', 3))
235
+ base_success = aux_data_quality * 15
236
+ privacy_penalty = (11 - epsilon) * 2
237
+ success_rate = max(25, min(95, base_success + privacy_penalty))
238
+
239
+ return jsonify({
240
+ 'attack_type': 'linkage_attack',
241
+ 'success_rate': round(success_rate, 1),
242
+ 'epsilon': epsilon,
243
+ 'aux_data_quality': aux_data_quality,
244
+ 'confidence': 'high' if success_rate > 75 else 'medium' if success_rate > 50 else 'low'
245
+ })
246
+
247
+ else:
248
+ return jsonify({'error': 'Unknown attack type'}), 400
249
+
250
+ except (TypeError, ValueError) as e:
251
+ return jsonify({'error': f'Invalid parameter values: {str(e)}'}), 400
252
+ except Exception as e:
253
+ return jsonify({'error': f'Server error: {str(e)}'}), 500
254
+
255
 
256
  # ===== Analytics & Identity Endpoints =====
257
  COOKIE_NAME = "vid"
app/static/js/attacks.js ADDED
@@ -0,0 +1,539 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Privacy Attacks Interactive Demonstrations
2
+ class AttackSimulator {
3
+ constructor() {
4
+ this.charts = {};
5
+ this.initializeEventListeners();
6
+ this.initializeCharts();
7
+ }
8
+
9
+ initializeEventListeners() {
10
+ // Tab switching
11
+ document.querySelectorAll('.attack-tab').forEach(tab => {
12
+ tab.addEventListener('click', (e) => {
13
+ this.switchTab(e.target.dataset.attack);
14
+ });
15
+ });
16
+
17
+ // Slider updates
18
+ this.setupSliderUpdates();
19
+ }
20
+
21
+ setupSliderUpdates() {
22
+ // New membership privacy level slider
23
+ const privacyLevelSlider = document.getElementById('privacy-level-slider');
24
+ if (privacyLevelSlider) {
25
+ privacyLevelSlider.addEventListener('input', (e) => {
26
+ const levels = ['Very High', 'High', 'Medium', 'Low', 'Very Low'];
27
+ document.getElementById('privacy-level-text').textContent = levels[e.target.value - 1];
28
+ this.updateMembershipDemo();
29
+ });
30
+ }
31
+
32
+ // Reconstruction sliders
33
+ const reconClipping = document.getElementById('recon-clipping-slider');
34
+ const reconNoise = document.getElementById('recon-noise-slider');
35
+
36
+ if (reconClipping) {
37
+ reconClipping.addEventListener('input', (e) => {
38
+ document.getElementById('recon-clipping').textContent = e.target.value;
39
+ this.updateReconstructionAttack();
40
+ });
41
+ }
42
+
43
+ if (reconNoise) {
44
+ reconNoise.addEventListener('input', (e) => {
45
+ document.getElementById('recon-noise-level').textContent = e.target.value;
46
+ this.updateReconstructionAttack();
47
+ });
48
+ }
49
+
50
+ // Linkage sliders
51
+ const linkageQuality = document.getElementById('linkage-quality-slider');
52
+ const linkagePrivacy = document.getElementById('linkage-privacy-slider');
53
+
54
+ if (linkageQuality) {
55
+ linkageQuality.addEventListener('input', (e) => {
56
+ const qualities = ['Very Low', 'Low', 'Medium', 'High', 'Very High'];
57
+ document.getElementById('linkage-quality').textContent = qualities[e.target.value - 1];
58
+ this.updateLinkageAttack();
59
+ });
60
+ }
61
+
62
+ if (linkagePrivacy) {
63
+ linkagePrivacy.addEventListener('input', (e) => {
64
+ const epsilon = (11 - e.target.value).toFixed(1);
65
+ document.getElementById('linkage-model-privacy').textContent = `ε=${epsilon}`;
66
+ this.updateLinkageAttack();
67
+ });
68
+ }
69
+ }
70
+
71
+ switchTab(attackType) {
72
+ // Update tab buttons
73
+ document.querySelectorAll('.attack-tab').forEach(tab => {
74
+ tab.classList.remove('active');
75
+ });
76
+ document.querySelector(`[data-attack="${attackType}"]`).classList.add('active');
77
+
78
+ // Update content
79
+ document.querySelectorAll('.attack-content').forEach(content => {
80
+ content.classList.remove('active');
81
+ });
82
+ document.getElementById(`${attackType}-content`).classList.add('active');
83
+
84
+ // Initialize chart for this tab if needed
85
+ this.initializeTabChart(attackType);
86
+ }
87
+
88
+ initializeCharts() {
89
+ this.initializeMembershipChart();
90
+ this.initializeComparisonChart();
91
+ }
92
+
93
+ initializeMembershipChart() {
94
+ const ctx = document.getElementById('membership-chart');
95
+ if (!ctx) return;
96
+
97
+ this.charts.membership = new Chart(ctx, {
98
+ type: 'line',
99
+ data: {
100
+ labels: ['ε=0.5', 'ε=1.0', 'ε=2.0', 'ε=3.0', 'ε=5.0', 'ε=8.0', 'ε=∞'],
101
+ datasets: [{
102
+ label: 'Attack Success Rate',
103
+ data: [52, 58, 65, 72, 78, 83, 87],
104
+ borderColor: '#ff6b6b',
105
+ backgroundColor: 'rgba(255, 107, 107, 0.1)',
106
+ tension: 0.4,
107
+ fill: true
108
+ }, {
109
+ label: 'Random Guessing',
110
+ data: [50, 50, 50, 50, 50, 50, 50],
111
+ borderColor: '#666',
112
+ borderDash: [5, 5],
113
+ fill: false
114
+ }]
115
+ },
116
+ options: {
117
+ responsive: true,
118
+ maintainAspectRatio: false,
119
+ plugins: {
120
+ title: {
121
+ display: true,
122
+ text: 'Membership Inference Attack Success vs Privacy Budget'
123
+ },
124
+ legend: {
125
+ display: true
126
+ }
127
+ },
128
+ scales: {
129
+ y: {
130
+ beginAtZero: true,
131
+ max: 100,
132
+ title: {
133
+ display: true,
134
+ text: 'Attack Success Rate (%)'
135
+ }
136
+ },
137
+ x: {
138
+ title: {
139
+ display: true,
140
+ text: 'Privacy Budget (ε)'
141
+ }
142
+ }
143
+ }
144
+ }
145
+ });
146
+ }
147
+
148
+ initializeComparisonChart() {
149
+ const ctx = document.getElementById('comparison-chart');
150
+ if (!ctx) return;
151
+
152
+ this.charts.comparison = new Chart(ctx, {
153
+ type: 'radar',
154
+ data: {
155
+ labels: ['Membership Inference', 'Data Reconstruction', 'Model Inversion', 'Property Inference', 'Linkage Attack'],
156
+ datasets: [{
157
+ label: 'No Privacy (ε=∞)',
158
+ data: [87, 92, 78, 83, 89],
159
+ borderColor: '#d32f2f',
160
+ backgroundColor: 'rgba(211, 47, 47, 0.2)',
161
+ pointBackgroundColor: '#d32f2f'
162
+ }, {
163
+ label: 'Low Privacy (ε=8.0)',
164
+ data: [72, 76, 65, 70, 74],
165
+ borderColor: '#f57c00',
166
+ backgroundColor: 'rgba(245, 124, 0, 0.2)',
167
+ pointBackgroundColor: '#f57c00'
168
+ }, {
169
+ label: 'Medium Privacy (ε=3.0)',
170
+ data: [58, 61, 52, 56, 60],
171
+ borderColor: '#fbc02d',
172
+ backgroundColor: 'rgba(251, 192, 45, 0.2)',
173
+ pointBackgroundColor: '#fbc02d'
174
+ }, {
175
+ label: 'High Privacy (ε=1.0)',
176
+ data: [42, 45, 38, 41, 44],
177
+ borderColor: '#2e7d32',
178
+ backgroundColor: 'rgba(46, 125, 50, 0.2)',
179
+ pointBackgroundColor: '#2e7d32'
180
+ }]
181
+ },
182
+ options: {
183
+ responsive: true,
184
+ maintainAspectRatio: false,
185
+ plugins: {
186
+ title: {
187
+ display: true,
188
+ text: 'Attack Success Rates Across Different Privacy Levels'
189
+ }
190
+ },
191
+ scales: {
192
+ r: {
193
+ beginAtZero: true,
194
+ max: 100,
195
+ ticks: {
196
+ stepSize: 20
197
+ }
198
+ }
199
+ }
200
+ }
201
+ });
202
+ }
203
+
204
+ initializeTabChart(attackType) {
205
+ if (attackType === 'reconstruction') {
206
+ this.initializeReconstructionChart();
207
+ } else if (attackType === 'property') {
208
+ this.initializePropertyChart();
209
+ } else if (attackType === 'linkage') {
210
+ this.initializeLinkageChart();
211
+ }
212
+ }
213
+
214
+ initializeReconstructionChart() {
215
+ const ctx = document.getElementById('reconstruction-chart');
216
+ if (!ctx || this.charts.reconstruction) return;
217
+
218
+ this.charts.reconstruction = new Chart(ctx, {
219
+ type: 'bar',
220
+ data: {
221
+ labels: ['No Noise', 'Low Noise (σ=0.5)', 'Medium Noise (σ=1.0)', 'High Noise (σ=2.0)', 'Very High Noise (σ=3.0)'],
222
+ datasets: [{
223
+ label: 'Reconstruction Quality (SSIM)',
224
+ data: [0.95, 0.78, 0.52, 0.31, 0.18],
225
+ backgroundColor: ['#d32f2f', '#f57c00', '#fbc02d', '#689f38', '#2e7d32'],
226
+ borderWidth: 1
227
+ }]
228
+ },
229
+ options: {
230
+ responsive: true,
231
+ maintainAspectRatio: false,
232
+ plugins: {
233
+ title: {
234
+ display: true,
235
+ text: 'Data Reconstruction Quality vs Noise Level'
236
+ }
237
+ },
238
+ scales: {
239
+ y: {
240
+ beginAtZero: true,
241
+ max: 1,
242
+ title: {
243
+ display: true,
244
+ text: 'Reconstruction Quality (SSIM Score)'
245
+ }
246
+ }
247
+ }
248
+ }
249
+ });
250
+ }
251
+
252
+ initializePropertyChart() {
253
+ const ctx = document.getElementById('property-chart');
254
+ if (!ctx || this.charts.property) return;
255
+
256
+ this.charts.property = new Chart(ctx, {
257
+ type: 'doughnut',
258
+ data: {
259
+ labels: ['Correctly Inferred', 'Incorrectly Inferred', 'Uncertain'],
260
+ datasets: [{
261
+ data: [52, 18, 30],
262
+ backgroundColor: ['#d32f2f', '#f57c00', '#2e7d32'],
263
+ borderWidth: 2
264
+ }]
265
+ },
266
+ options: {
267
+ responsive: true,
268
+ maintainAspectRatio: false,
269
+ plugins: {
270
+ title: {
271
+ display: true,
272
+ text: 'Property Inference Attack Results'
273
+ },
274
+ legend: {
275
+ position: 'bottom'
276
+ }
277
+ }
278
+ }
279
+ });
280
+ }
281
+
282
+ initializeLinkageChart() {
283
+ const ctx = document.getElementById('linkage-chart');
284
+ if (!ctx || this.charts.linkage) return;
285
+
286
+ this.charts.linkage = new Chart(ctx, {
287
+ type: 'scatter',
288
+ data: {
289
+ datasets: [{
290
+ label: 'Successful Links',
291
+ data: [
292
+ {x: 1, y: 45}, {x: 2, y: 52}, {x: 3, y: 61}, {x: 4, y: 68}, {x: 5, y: 74},
293
+ {x: 6, y: 79}, {x: 7, y: 83}, {x: 8, y: 86}, {x: 9, y: 89}, {x: 10, y: 91}
294
+ ],
295
+ backgroundColor: '#d32f2f',
296
+ borderColor: '#d32f2f'
297
+ }]
298
+ },
299
+ options: {
300
+ responsive: true,
301
+ maintainAspectRatio: false,
302
+ plugins: {
303
+ title: {
304
+ display: true,
305
+ text: 'Linkage Attack Success vs Privacy Budget'
306
+ }
307
+ },
308
+ scales: {
309
+ x: {
310
+ title: {
311
+ display: true,
312
+ text: 'Privacy Budget (ε)'
313
+ },
314
+ min: 0,
315
+ max: 11
316
+ },
317
+ y: {
318
+ title: {
319
+ display: true,
320
+ text: 'Successful Links (%)'
321
+ },
322
+ min: 0,
323
+ max: 100
324
+ }
325
+ }
326
+ }
327
+ });
328
+ }
329
+
330
+ // Attack simulation functions
331
+ updateMembershipDemo() {
332
+ const privacyLevel = parseInt(document.getElementById('privacy-level-slider').value);
333
+
334
+ // Calculate attack success based on privacy level (1=highest privacy, 5=lowest)
335
+ const successRates = [45, 52, 65, 78, 87]; // Success rates for each privacy level
336
+ const successRate = successRates[privacyLevel - 1];
337
+
338
+ // Update confidence differences based on privacy
339
+ const confidenceDiffs = [6, 8, 14, 22, 28]; // Confidence differences
340
+ const trainingConf = [88, 90, 92, 94, 96]; // Training confidence
341
+ const testConf = trainingConf.map((tc, i) => tc - confidenceDiffs[i]); // Test confidence
342
+
343
+ const currentTrainingConf = trainingConf[privacyLevel - 1];
344
+ const currentTestConf = testConf[privacyLevel - 1];
345
+ const currentDiff = confidenceDiffs[privacyLevel - 1];
346
+
347
+ // Update visual elements
348
+ document.getElementById('training-confidence').style.width = `${currentTrainingConf}%`;
349
+ document.getElementById('training-confidence').textContent = `${currentTrainingConf}%`;
350
+
351
+ document.getElementById('test-confidence').style.width = `${currentTestConf}%`;
352
+ document.getElementById('test-confidence').textContent = `${currentTestConf}%`;
353
+
354
+ document.getElementById('confidence-diff').textContent = `${currentDiff}%`;
355
+
356
+ // Update success rate circle
357
+ document.getElementById('membership-success').textContent = `${successRate}%`;
358
+
359
+ // Update circle color based on success rate
360
+ const circle = document.getElementById('success-rate-circle');
361
+ if (successRate < 55) {
362
+ circle.style.background = 'linear-gradient(135deg, #28a745, #20c997)'; // Green - good privacy
363
+ } else if (successRate < 70) {
364
+ circle.style.background = 'linear-gradient(135deg, #ffc107, #fd7e14)'; // Yellow - medium privacy
365
+ } else {
366
+ circle.style.background = 'linear-gradient(135deg, #dc3545, #fd7e14)'; // Red - poor privacy
367
+ }
368
+
369
+ // Update explanation text
370
+ const explanations = [
371
+ "Excellent! With very high privacy protection, the attacker can barely do better than random guessing (50%). Your data is well protected!",
372
+ "Great! High privacy protection makes the attack much less effective. The confidence differences are small and hard to exploit.",
373
+ "With medium privacy protection, the attacker can still succeed 65% of the time. Consider increasing privacy for sensitive data.",
374
+ "Low privacy protection allows attackers to succeed most of the time. The model shows clear differences between training and test data.",
375
+ "Very low privacy means the attack is highly successful. The model 'remembers' training data too well, making membership easy to detect."
376
+ ];
377
+
378
+ document.getElementById('privacy-explanation').textContent = explanations[privacyLevel - 1];
379
+ }
380
+
381
+ updateReconstructionAttack() {
382
+ const clipping = parseFloat(document.getElementById('recon-clipping-slider').value);
383
+ const noise = parseFloat(document.getElementById('recon-noise-slider').value);
384
+
385
+ // Calculate reconstruction quality
386
+ const baseQuality = 0.95;
387
+ const clippingReduction = (5 - clipping) * 0.1;
388
+ const noiseReduction = noise * 0.25;
389
+
390
+ const quality = Math.max(0.1, baseQuality - clippingReduction - noiseReduction);
391
+
392
+ const qualityElement = document.getElementById('recon-quality');
393
+ if (quality > 0.7) {
394
+ qualityElement.textContent = 'High Quality';
395
+ qualityElement.className = 'reconstruction-quality quality-high';
396
+ } else if (quality > 0.4) {
397
+ qualityElement.textContent = 'Medium Quality';
398
+ qualityElement.className = 'reconstruction-quality quality-medium';
399
+ } else {
400
+ qualityElement.textContent = 'Low Quality';
401
+ qualityElement.className = 'reconstruction-quality quality-low';
402
+ }
403
+ }
404
+
405
+ updateLinkageAttack() {
406
+ const quality = parseInt(document.getElementById('linkage-quality-slider').value);
407
+ const privacy = parseInt(document.getElementById('linkage-privacy-slider').value);
408
+
409
+ // Calculate linkage success
410
+ const baseSuccess = quality * 15; // Quality factor
411
+ const privacyPenalty = (11 - privacy) * 2; // Privacy factor
412
+
413
+ const successRate = Math.max(25, Math.min(95, baseSuccess + privacyPenalty));
414
+
415
+ document.getElementById('linkage-success').textContent = `${Math.round(successRate)}%`;
416
+
417
+ // Update confidence
418
+ const confidence = document.getElementById('linkage-confidence');
419
+ if (successRate > 75) {
420
+ confidence.textContent = 'High';
421
+ } else if (successRate > 50) {
422
+ confidence.textContent = 'Medium';
423
+ } else {
424
+ confidence.textContent = 'Low';
425
+ }
426
+ }
427
+ }
428
+
429
+ // Attack simulation functions (called by buttons)
430
+ function updatePrivacyDemo() {
431
+ const simulator = window.attackSimulator;
432
+ simulator.updateMembershipDemo();
433
+
434
+ // Add visual feedback
435
+ const button = event.target;
436
+ const originalText = button.textContent;
437
+ button.textContent = 'Updating...';
438
+ button.disabled = true;
439
+
440
+ setTimeout(() => {
441
+ button.textContent = originalText;
442
+ button.disabled = false;
443
+ }, 800);
444
+ }
445
+
446
+ function runReconstructionAttack() {
447
+ const simulator = window.attackSimulator;
448
+ simulator.updateReconstructionAttack();
449
+
450
+ // Add visual feedback
451
+ const button = event.target;
452
+ const originalText = button.textContent;
453
+ button.textContent = 'Reconstructing...';
454
+ button.disabled = true;
455
+
456
+ setTimeout(() => {
457
+ button.textContent = originalText;
458
+ button.disabled = false;
459
+ }, 2000);
460
+ }
461
+
462
+ function runInversionAttack() {
463
+ const classSelect = document.getElementById('inversion-class-select');
464
+ const privacySlider = document.getElementById('inversion-privacy-slider');
465
+
466
+ const selectedClass = classSelect.value;
467
+ const privacyLevel = parseInt(privacySlider.value);
468
+
469
+ // Calculate confidence based on privacy level
470
+ const confidence = Math.max(30, 95 - (privacyLevel * 6));
471
+ document.getElementById('inversion-confidence').textContent = `${confidence}%`;
472
+
473
+ // Update class display
474
+ document.getElementById('inversion-class').textContent = classSelect.options[classSelect.selectedIndex].text;
475
+
476
+ // Add visual feedback
477
+ const button = event.target;
478
+ const originalText = button.textContent;
479
+ button.textContent = 'Generating...';
480
+ button.disabled = true;
481
+
482
+ setTimeout(() => {
483
+ button.textContent = originalText;
484
+ button.disabled = false;
485
+ }, 1800);
486
+ }
487
+
488
+ function runPropertyAttack() {
489
+ const propertyType = document.getElementById('property-type').value;
490
+ const accessLevel = parseInt(document.getElementById('property-access-slider').value);
491
+
492
+ // Calculate property inference accuracy
493
+ const baseAccuracy = 70;
494
+ const accessBonus = accessLevel * 8;
495
+ const accuracy = Math.min(95, baseAccuracy + accessBonus);
496
+
497
+ // Update uncertainty based on privacy (simulated)
498
+ const uncertainty = Math.max(3, 15 - accessLevel * 2);
499
+
500
+ document.getElementById('property-male').textContent = `${52}% ± ${uncertainty}%`;
501
+ document.getElementById('property-female').textContent = `${48}% ± ${uncertainty}%`;
502
+
503
+ // Add visual feedback
504
+ const button = event.target;
505
+ const originalText = button.textContent;
506
+ button.textContent = 'Analyzing...';
507
+ button.disabled = true;
508
+
509
+ setTimeout(() => {
510
+ button.textContent = originalText;
511
+ button.disabled = false;
512
+ }, 2200);
513
+ }
514
+
515
+ function runLinkageAttack() {
516
+ const simulator = window.attackSimulator;
517
+ simulator.updateLinkageAttack();
518
+
519
+ // Add visual feedback
520
+ const button = event.target;
521
+ const originalText = button.textContent;
522
+ button.textContent = 'Linking Data...';
523
+ button.disabled = true;
524
+
525
+ setTimeout(() => {
526
+ button.textContent = originalText;
527
+ button.disabled = false;
528
+ }, 2500);
529
+ }
530
+
531
+ // Initialize when page loads
532
+ document.addEventListener('DOMContentLoaded', function() {
533
+ window.attackSimulator = new AttackSimulator();
534
+
535
+ // Run initial updates
536
+ window.attackSimulator.updateMembershipDemo();
537
+ window.attackSimulator.updateReconstructionAttack();
538
+ window.attackSimulator.updateLinkageAttack();
539
+ });
app/templates/attacks.html ADDED
@@ -0,0 +1,1092 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends "base.html" %}
2
+
3
+ {% block title %}Privacy Attacks - DP-SGD Explorer{% endblock %}
4
+
5
+ {% block extra_head %}
6
+ <style>
7
+ .attacks-container {
8
+ max-width: 1200px;
9
+ margin: 0 auto;
10
+ padding: 2rem;
11
+ }
12
+
13
+ .attack-tabs {
14
+ display: flex;
15
+ background-color: var(--background-off);
16
+ border-radius: 8px;
17
+ padding: 4px;
18
+ margin-bottom: 2rem;
19
+ overflow-x: auto;
20
+ }
21
+
22
+ .attack-tab {
23
+ flex: 1;
24
+ min-width: 150px;
25
+ padding: 0.75rem 1rem;
26
+ text-align: center;
27
+ background: transparent;
28
+ border: none;
29
+ border-radius: 4px;
30
+ cursor: pointer;
31
+ font-weight: 500;
32
+ transition: all 0.3s ease;
33
+ white-space: nowrap;
34
+ }
35
+
36
+ .attack-tab:hover {
37
+ background-color: rgba(255, 255, 255, 0.1);
38
+ }
39
+
40
+ .attack-tab.active {
41
+ background-color: var(--primary-color);
42
+ color: white;
43
+ }
44
+
45
+ .attack-content {
46
+ display: none;
47
+ animation: fadeIn 0.3s ease-in;
48
+ }
49
+
50
+ .attack-content.active {
51
+ display: block;
52
+ }
53
+
54
+ @keyframes fadeIn {
55
+ from { opacity: 0; transform: translateY(10px); }
56
+ to { opacity: 1; transform: translateY(0); }
57
+ }
58
+
59
+ .attack-header {
60
+ text-align: center;
61
+ margin-bottom: 2rem;
62
+ padding: 2rem;
63
+ background: linear-gradient(135deg, #ff6b6b, #ee5a24);
64
+ color: white;
65
+ border-radius: 12px;
66
+ }
67
+
68
+ .attack-header h1 {
69
+ margin: 0 0 0.5rem 0;
70
+ font-size: 2.5rem;
71
+ }
72
+
73
+ .attack-header p {
74
+ margin: 0;
75
+ font-size: 1.1rem;
76
+ opacity: 0.9;
77
+ }
78
+
79
+ .attack-section {
80
+ background: white;
81
+ border-radius: 12px;
82
+ padding: 2rem;
83
+ margin-bottom: 2rem;
84
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
85
+ }
86
+
87
+ .attack-title {
88
+ display: flex;
89
+ align-items: center;
90
+ gap: 1rem;
91
+ margin-bottom: 1rem;
92
+ }
93
+
94
+ .attack-icon {
95
+ font-size: 2rem;
96
+ width: 60px;
97
+ height: 60px;
98
+ display: flex;
99
+ align-items: center;
100
+ justify-content: center;
101
+ border-radius: 50%;
102
+ background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
103
+ }
104
+
105
+ .attack-demo {
106
+ display: grid;
107
+ grid-template-columns: 1fr 1fr;
108
+ gap: 2rem;
109
+ margin: 2rem 0;
110
+ }
111
+
112
+ .demo-panel {
113
+ background: var(--background-off);
114
+ padding: 1.5rem;
115
+ border-radius: 8px;
116
+ }
117
+
118
+ .demo-controls {
119
+ margin-bottom: 1rem;
120
+ }
121
+
122
+ .demo-slider {
123
+ width: 100%;
124
+ margin: 0.5rem 0;
125
+ }
126
+
127
+ .demo-result {
128
+ background: white;
129
+ padding: 1rem;
130
+ border-radius: 4px;
131
+ margin-top: 1rem;
132
+ border-left: 4px solid var(--primary-color);
133
+ }
134
+
135
+ .success-rate {
136
+ font-size: 1.5rem;
137
+ font-weight: bold;
138
+ color: var(--primary-color);
139
+ }
140
+
141
+ .privacy-level {
142
+ display: inline-block;
143
+ padding: 0.25rem 0.5rem;
144
+ border-radius: 4px;
145
+ font-size: 0.8rem;
146
+ font-weight: 500;
147
+ margin-left: 0.5rem;
148
+ }
149
+
150
+ .privacy-high { background: #e8f5e8; color: #2e7d32; }
151
+ .privacy-medium { background: #fff3e0; color: #f57c00; }
152
+ .privacy-low { background: #ffebee; color: #d32f2f; }
153
+
154
+ .comparison-grid {
155
+ display: grid;
156
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
157
+ gap: 1rem;
158
+ margin: 2rem 0;
159
+ }
160
+
161
+ .comparison-card {
162
+ background: var(--background-off);
163
+ padding: 1.5rem;
164
+ border-radius: 8px;
165
+ text-align: center;
166
+ }
167
+
168
+ .comparison-value {
169
+ font-size: 2rem;
170
+ font-weight: bold;
171
+ margin: 0.5rem 0;
172
+ }
173
+
174
+ .defense-section {
175
+ background: linear-gradient(135deg, #4caf50, #2e7d32);
176
+ color: white;
177
+ padding: 2rem;
178
+ border-radius: 12px;
179
+ margin-top: 2rem;
180
+ }
181
+
182
+ .defense-grid {
183
+ display: grid;
184
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
185
+ gap: 1.5rem;
186
+ margin-top: 1.5rem;
187
+ }
188
+
189
+ .defense-item {
190
+ background: rgba(255, 255, 255, 0.1);
191
+ padding: 1.5rem;
192
+ border-radius: 8px;
193
+ }
194
+
195
+ .chart-container {
196
+ position: relative;
197
+ height: 300px;
198
+ margin: 1rem 0;
199
+ }
200
+
201
+ .visual-demo {
202
+ display: grid;
203
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
204
+ gap: 1rem;
205
+ margin: 1.5rem 0;
206
+ }
207
+
208
+ .visual-item {
209
+ text-align: center;
210
+ padding: 1rem;
211
+ background: var(--background-off);
212
+ border-radius: 8px;
213
+ }
214
+
215
+ .visual-item img {
216
+ max-width: 100%;
217
+ height: 120px;
218
+ object-fit: cover;
219
+ border-radius: 4px;
220
+ margin-bottom: 0.5rem;
221
+ }
222
+
223
+ .reconstruction-quality {
224
+ font-weight: bold;
225
+ padding: 0.25rem 0.5rem;
226
+ border-radius: 4px;
227
+ font-size: 0.8rem;
228
+ }
229
+
230
+ .quality-high { background: #ffebee; color: #d32f2f; }
231
+ .quality-medium { background: #fff3e0; color: #f57c00; }
232
+ .quality-low { background: #e8f5e8; color: #2e7d32; }
233
+
234
+ .linkage-demo {
235
+ display: grid;
236
+ grid-template-columns: 1fr auto 1fr auto 1fr;
237
+ gap: 1rem;
238
+ align-items: center;
239
+ margin: 2rem 0;
240
+ }
241
+
242
+ .linkage-source {
243
+ background: var(--background-off);
244
+ padding: 1rem;
245
+ border-radius: 8px;
246
+ text-align: center;
247
+ }
248
+
249
+ .linkage-arrow {
250
+ font-size: 1.5rem;
251
+ color: var(--primary-color);
252
+ }
253
+
254
+ .warning-box {
255
+ background: #fff3cd;
256
+ border: 1px solid #ffeaa7;
257
+ color: #856404;
258
+ padding: 1rem;
259
+ border-radius: 8px;
260
+ margin: 1rem 0;
261
+ }
262
+
263
+ .info-box {
264
+ background: #d1ecf1;
265
+ border: 1px solid #bee5eb;
266
+ color: #0c5460;
267
+ padding: 1rem;
268
+ border-radius: 8px;
269
+ margin: 1rem 0;
270
+ }
271
+
272
+ /* Membership Attack Specific Styles */
273
+ .attack-story {
274
+ margin: 2rem 0;
275
+ }
276
+
277
+ .story-flow {
278
+ display: flex;
279
+ align-items: center;
280
+ gap: 1rem;
281
+ margin: 2rem 0;
282
+ overflow-x: auto;
283
+ padding: 1rem 0;
284
+ }
285
+
286
+ .story-card {
287
+ background: white;
288
+ border-radius: 12px;
289
+ padding: 1.5rem;
290
+ min-width: 200px;
291
+ flex-shrink: 0;
292
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
293
+ border: 2px solid #e9ecef;
294
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
295
+ }
296
+
297
+ .story-card:hover {
298
+ transform: translateY(-2px);
299
+ box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
300
+ }
301
+
302
+ .story-card.danger {
303
+ border-color: #dc3545;
304
+ background: linear-gradient(135deg, #fff5f5, #ffe6e6);
305
+ }
306
+
307
+ .story-icon {
308
+ font-size: 2.5rem;
309
+ text-align: center;
310
+ margin-bottom: 1rem;
311
+ }
312
+
313
+ .story-content h4 {
314
+ margin: 0 0 0.75rem 0;
315
+ color: #333;
316
+ font-size: 1.1rem;
317
+ text-align: center;
318
+ }
319
+
320
+ .story-content p {
321
+ margin: 0;
322
+ line-height: 1.5;
323
+ color: #666;
324
+ text-align: center;
325
+ font-size: 0.9rem;
326
+ }
327
+
328
+ .story-arrow {
329
+ font-size: 1.5rem;
330
+ color: var(--primary-color);
331
+ font-weight: bold;
332
+ flex-shrink: 0;
333
+ }
334
+
335
+ /* Mobile responsive */
336
+ @media (max-width: 768px) {
337
+ .story-flow {
338
+ flex-direction: column;
339
+ }
340
+
341
+ .story-arrow {
342
+ transform: rotate(90deg);
343
+ }
344
+
345
+ .story-card {
346
+ min-width: auto;
347
+ width: 100%;
348
+ }
349
+ }
350
+
351
+ .interactive-demo {
352
+ background: #f8f9fa;
353
+ padding: 2rem;
354
+ border-radius: 12px;
355
+ margin: 2rem 0;
356
+ }
357
+
358
+ .demo-scenario {
359
+ margin-top: 1.5rem;
360
+ }
361
+
362
+ .scenario-setup {
363
+ text-align: center;
364
+ margin-bottom: 2rem;
365
+ }
366
+
367
+ .confidence-comparison {
368
+ display: grid;
369
+ grid-template-columns: 1fr auto 1fr;
370
+ gap: 2rem;
371
+ align-items: center;
372
+ margin: 2rem 0;
373
+ }
374
+
375
+ .data-sample {
376
+ background: white;
377
+ padding: 1.5rem;
378
+ border-radius: 8px;
379
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
380
+ }
381
+
382
+ .sample-header {
383
+ display: flex;
384
+ justify-content: space-between;
385
+ align-items: center;
386
+ margin-bottom: 1rem;
387
+ }
388
+
389
+ .sample-label {
390
+ font-weight: 600;
391
+ color: #333;
392
+ }
393
+
394
+ .sample-status {
395
+ padding: 0.25rem 0.75rem;
396
+ border-radius: 20px;
397
+ font-size: 0.8rem;
398
+ font-weight: 500;
399
+ }
400
+
401
+ .sample-status.training {
402
+ background: #d4edda;
403
+ color: #155724;
404
+ }
405
+
406
+ .sample-status.test {
407
+ background: #f8d7da;
408
+ color: #721c24;
409
+ }
410
+
411
+ .sample-image {
412
+ text-align: center;
413
+ margin: 1rem 0;
414
+ }
415
+
416
+ .digit-display {
417
+ width: 80px;
418
+ height: 80px;
419
+ background: #e9ecef;
420
+ border-radius: 8px;
421
+ display: flex;
422
+ align-items: center;
423
+ justify-content: center;
424
+ font-size: 2.5rem;
425
+ font-weight: bold;
426
+ color: #495057;
427
+ margin: 0 auto;
428
+ }
429
+
430
+ .confidence-bar {
431
+ margin-top: 1rem;
432
+ }
433
+
434
+ .confidence-label {
435
+ font-size: 0.9rem;
436
+ color: #666;
437
+ margin-bottom: 0.5rem;
438
+ }
439
+
440
+ .confidence-meter {
441
+ background: #e9ecef;
442
+ height: 30px;
443
+ border-radius: 15px;
444
+ position: relative;
445
+ overflow: hidden;
446
+ }
447
+
448
+ .confidence-fill {
449
+ height: 100%;
450
+ border-radius: 15px;
451
+ display: flex;
452
+ align-items: center;
453
+ justify-content: center;
454
+ font-weight: bold;
455
+ color: white;
456
+ transition: width 0.5s ease;
457
+ }
458
+
459
+ .training-confidence {
460
+ background: linear-gradient(90deg, #dc3545, #fd7e14);
461
+ }
462
+
463
+ .test-confidence {
464
+ background: linear-gradient(90deg, #28a745, #20c997);
465
+ }
466
+
467
+ .vs-divider {
468
+ font-size: 1.5rem;
469
+ font-weight: bold;
470
+ color: var(--primary-color);
471
+ text-align: center;
472
+ }
473
+
474
+ .attack-insight {
475
+ margin-top: 2rem;
476
+ }
477
+
478
+ .insight-box {
479
+ background: linear-gradient(135deg, #fff3cd, #ffeaa7);
480
+ border: 1px solid #ffeaa7;
481
+ color: #856404;
482
+ padding: 1.5rem;
483
+ border-radius: 8px;
484
+ text-align: center;
485
+ font-size: 1.1rem;
486
+ }
487
+
488
+ .privacy-demo {
489
+ background: white;
490
+ padding: 2rem;
491
+ border-radius: 12px;
492
+ margin: 2rem 0;
493
+ border: 2px solid var(--primary-color);
494
+ }
495
+
496
+ .privacy-controls {
497
+ display: grid;
498
+ grid-template-columns: 1fr 1fr;
499
+ gap: 2rem;
500
+ margin-top: 1.5rem;
501
+ }
502
+
503
+ .control-panel {
504
+ background: var(--background-off);
505
+ padding: 1.5rem;
506
+ border-radius: 8px;
507
+ }
508
+
509
+ .privacy-scale {
510
+ display: flex;
511
+ justify-content: space-between;
512
+ font-size: 0.8rem;
513
+ color: #666;
514
+ margin-top: 0.5rem;
515
+ }
516
+
517
+ .privacy-results {
518
+ text-align: center;
519
+ }
520
+
521
+ .success-rate-display {
522
+ margin: 1.5rem 0;
523
+ }
524
+
525
+ .rate-circle {
526
+ width: 120px;
527
+ height: 120px;
528
+ border-radius: 50%;
529
+ background: linear-gradient(135deg, #ff6b6b, #ee5a24);
530
+ color: white;
531
+ display: flex;
532
+ flex-direction: column;
533
+ align-items: center;
534
+ justify-content: center;
535
+ margin: 0 auto;
536
+ box-shadow: 0 4px 8px rgba(0,0,0,0.2);
537
+ }
538
+
539
+ .rate-number {
540
+ font-size: 1.8rem;
541
+ font-weight: bold;
542
+ }
543
+
544
+ .rate-label {
545
+ font-size: 0.9rem;
546
+ opacity: 0.9;
547
+ }
548
+
549
+ .privacy-explanation {
550
+ background: var(--background-off);
551
+ padding: 1rem;
552
+ border-radius: 8px;
553
+ margin-top: 1rem;
554
+ font-size: 0.9rem;
555
+ line-height: 1.5;
556
+ }
557
+
558
+ .real-world-examples {
559
+ margin: 2rem 0;
560
+ }
561
+
562
+ .example-grid {
563
+ display: grid;
564
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
565
+ gap: 1.5rem;
566
+ margin: 1.5rem 0;
567
+ }
568
+
569
+ .example-card {
570
+ background: white;
571
+ padding: 1.5rem;
572
+ border-radius: 8px;
573
+ text-align: center;
574
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
575
+ border-left: 4px solid var(--primary-color);
576
+ }
577
+
578
+ .example-icon {
579
+ font-size: 2.5rem;
580
+ margin-bottom: 1rem;
581
+ }
582
+
583
+ .example-card h4 {
584
+ margin: 0 0 1rem 0;
585
+ color: var(--primary-color);
586
+ }
587
+
588
+ .example-card p {
589
+ margin: 0;
590
+ color: #666;
591
+ line-height: 1.5;
592
+ }
593
+ </style>
594
+ {% endblock %}
595
+
596
+ {% block content %}
597
+ <div class="attacks-container">
598
+ <!-- Header Section -->
599
+ <div class="attack-header">
600
+ <h1>🛡️ Privacy Attacks in Machine Learning</h1>
601
+ <p>Understand the threats that differential privacy protects against</p>
602
+ </div>
603
+
604
+ <!-- Navigation Tabs -->
605
+ <div class="attack-tabs">
606
+ <button class="attack-tab active" data-attack="membership">Membership Inference</button>
607
+ <button class="attack-tab" data-attack="reconstruction">Data Reconstruction</button>
608
+ <button class="attack-tab" data-attack="inversion">Model Inversion</button>
609
+ <button class="attack-tab" data-attack="property">Property Inference</button>
610
+ <button class="attack-tab" data-attack="linkage">Linkage Attack</button>
611
+ <button class="attack-tab" data-attack="comparison">Attack Comparison</button>
612
+ </div>
613
+
614
+ <!-- Membership Inference Attack -->
615
+ <div id="membership-content" class="attack-content active">
616
+ <div class="attack-section">
617
+ <div class="attack-title">
618
+ <div class="attack-icon">🎯</div>
619
+ <div>
620
+ <h2>Membership Inference Attack</h2>
621
+ <p>Can an attacker tell if your data was used to train this model?</p>
622
+ </div>
623
+ </div>
624
+
625
+ <!-- Story-based explanation -->
626
+ <div class="attack-story">
627
+ <h3>🤔 What is this attack?</h3>
628
+ <div class="story-flow">
629
+ <div class="story-card">
630
+ <div class="story-icon">🏥</div>
631
+ <div class="story-content">
632
+ <h4>A Hospital's AI Model</h4>
633
+ <p>A hospital trains an AI to diagnose diseases using patient records. Alice was one of the patients whose data was used.</p>
634
+ </div>
635
+ </div>
636
+
637
+ <div class="story-arrow">→</div>
638
+
639
+ <div class="story-card">
640
+ <div class="story-icon">🕵️</div>
641
+ <div class="story-content">
642
+ <h4>An Attacker's Question</h4>
643
+ <p><strong>"Was Alice's medical record used to train this model?"</strong> The attacker wants to know if Alice was a patient here.</p>
644
+ </div>
645
+ </div>
646
+
647
+ <div class="story-arrow">→</div>
648
+
649
+ <div class="story-card">
650
+ <div class="story-icon">🎯</div>
651
+ <div class="story-content">
652
+ <h4>The Attack Trick</h4>
653
+ <p>The attacker feeds Alice's data to the model and checks: <strong>"How confident is the model?"</strong> Models remember training data!</p>
654
+ </div>
655
+ </div>
656
+
657
+ <div class="story-arrow">→</div>
658
+
659
+ <div class="story-card danger">
660
+ <div class="story-icon">⚠️</div>
661
+ <div class="story-content">
662
+ <h4>Privacy Breach!</h4>
663
+ <p>If the model is very confident, the attacker learns Alice was a patient at this hospital - a serious privacy violation!</p>
664
+ </div>
665
+ </div>
666
+ </div>
667
+ </div>
668
+
669
+ <!-- Interactive Demo -->
670
+ <div class="interactive-demo">
671
+ <h3>🧪 Try the Attack Yourself</h3>
672
+ <div class="demo-scenario">
673
+ <div class="scenario-setup">
674
+ <h4>The Setup</h4>
675
+ <p>We have a model trained to recognize handwritten digits. Let's see if we can tell which images were in the training set!</p>
676
+ </div>
677
+
678
+ <div class="confidence-comparison">
679
+ <div class="data-sample">
680
+ <div class="sample-header">
681
+ <span class="sample-label">Training Data Sample</span>
682
+ <span class="sample-status training">✓ Was in training</span>
683
+ </div>
684
+ <div class="sample-image">
685
+ <div class="digit-display">7</div>
686
+ </div>
687
+ <div class="confidence-bar">
688
+ <div class="confidence-label">Model Confidence:</div>
689
+ <div class="confidence-meter">
690
+ <div class="confidence-fill training-confidence" id="training-confidence" style="width: 92%;">92%</div>
691
+ </div>
692
+ </div>
693
+ </div>
694
+
695
+ <div class="vs-divider">VS</div>
696
+
697
+ <div class="data-sample">
698
+ <div class="sample-header">
699
+ <span class="sample-label">Test Data Sample</span>
700
+ <span class="sample-status test">✗ Not in training</span>
701
+ </div>
702
+ <div class="sample-image">
703
+ <div class="digit-display">7</div>
704
+ </div>
705
+ <div class="confidence-bar">
706
+ <div class="confidence-label">Model Confidence:</div>
707
+ <div class="confidence-meter">
708
+ <div class="confidence-fill test-confidence" id="test-confidence" style="width: 78%;">78%</div>
709
+ </div>
710
+ </div>
711
+ </div>
712
+ </div>
713
+
714
+ <div class="attack-insight">
715
+ <div class="insight-box">
716
+ <strong>🔍 The Attack Insight:</strong> The model is <span id="confidence-diff">14%</span> more confident on training data!
717
+ An attacker can use this difference to guess membership.
718
+ </div>
719
+ </div>
720
+ </div>
721
+ </div>
722
+
723
+ <!-- Privacy Protection Demo -->
724
+ <div class="privacy-demo">
725
+ <h3>🛡️ How Does Differential Privacy Help?</h3>
726
+ <div class="privacy-controls">
727
+ <div class="control-panel">
728
+ <h4>Adjust Privacy Protection</h4>
729
+ <div class="demo-controls">
730
+ <label>Privacy Level: <span id="privacy-level-text">Medium</span></label>
731
+ <input type="range" class="demo-slider" id="privacy-level-slider" min="1" max="5" step="1" value="3">
732
+ <div class="privacy-scale">
733
+ <span>High Privacy</span>
734
+ <span>Low Privacy</span>
735
+ </div>
736
+ </div>
737
+ <button class="control-button" onclick="updatePrivacyDemo()">Update Protection</button>
738
+ </div>
739
+
740
+ <div class="privacy-results">
741
+ <h4>Attack Success Rate</h4>
742
+ <div class="success-rate-display">
743
+ <div class="rate-circle" id="success-rate-circle">
744
+ <span class="rate-number" id="membership-success">65%</span>
745
+ <span class="rate-label">Success</span>
746
+ </div>
747
+ </div>
748
+ <div class="privacy-explanation" id="privacy-explanation">
749
+ With medium privacy protection, the attacker can still succeed 65% of the time. Try increasing privacy!
750
+ </div>
751
+ </div>
752
+ </div>
753
+ </div>
754
+
755
+ <!-- Real-world Examples -->
756
+ <div class="real-world-examples">
757
+ <h3>🌍 Real-World Impact</h3>
758
+ <div class="example-grid">
759
+ <div class="example-card">
760
+ <div class="example-icon">🏥</div>
761
+ <h4>Healthcare</h4>
762
+ <p>Revealing if someone's medical data was used in training could expose their health conditions</p>
763
+ </div>
764
+ <div class="example-card">
765
+ <div class="example-icon">💳</div>
766
+ <h4>Finance</h4>
767
+ <p>Knowing if someone's financial data was in training could reveal their banking relationships</p>
768
+ </div>
769
+ <div class="example-card">
770
+ <div class="example-icon">📱</div>
771
+ <h4>Social Media</h4>
772
+ <p>Determining if someone's posts were used could reveal their participation in studies</p>
773
+ </div>
774
+ </div>
775
+ </div>
776
+
777
+ <div class="chart-container">
778
+ <canvas id="membership-chart"></canvas>
779
+ </div>
780
+ </div>
781
+ </div>
782
+
783
+ <!-- Data Reconstruction Attack -->
784
+ <div id="reconstruction-content" class="attack-content">
785
+ <div class="attack-section">
786
+ <div class="attack-title">
787
+ <div class="attack-icon">🔍</div>
788
+ <div>
789
+ <h2>Data Reconstruction Attack</h2>
790
+ <p>Recover training data from model gradients</p>
791
+ </div>
792
+ </div>
793
+
794
+ <div class="warning-box">
795
+ <strong>Threat:</strong> Attackers with access to gradients can potentially reconstruct original training images, especially in federated learning scenarios.
796
+ </div>
797
+
798
+ <div class="attack-demo">
799
+ <div class="demo-panel">
800
+ <h3>Gradient Privacy Settings</h3>
801
+ <div class="demo-controls">
802
+ <label>Clipping Norm: <span id="recon-clipping">1.0</span></label>
803
+ <input type="range" class="demo-slider" id="recon-clipping-slider" min="0.1" max="5" step="0.1" value="1.0">
804
+
805
+ <label>Noise Level: <span id="recon-noise-level">1.0</span></label>
806
+ <input type="range" class="demo-slider" id="recon-noise-slider" min="0" max="3" step="0.1" value="1.0">
807
+ </div>
808
+ <button class="control-button" onclick="runReconstructionAttack()">Simulate Reconstruction</button>
809
+ </div>
810
+
811
+ <div class="demo-panel">
812
+ <h3>Reconstruction Quality</h3>
813
+ <div class="visual-demo">
814
+ <div class="visual-item">
815
+ <div style="width: 120px; height: 120px; background: #f0f0f0; border-radius: 4px; margin: 0 auto 0.5rem; display: flex; align-items: center; justify-content: center;">
816
+ Original Image
817
+ </div>
818
+ <div>Ground Truth</div>
819
+ </div>
820
+ <div class="visual-item">
821
+ <div style="width: 120px; height: 120px; background: #ffcccb; border-radius: 4px; margin: 0 auto 0.5rem; display: flex; align-items: center; justify-content: center;">
822
+ Reconstructed
823
+ </div>
824
+ <div class="reconstruction-quality quality-high" id="recon-quality">High Quality</div>
825
+ </div>
826
+ </div>
827
+ </div>
828
+ </div>
829
+
830
+ <div class="chart-container">
831
+ <canvas id="reconstruction-chart"></canvas>
832
+ </div>
833
+ </div>
834
+ </div>
835
+
836
+ <!-- Model Inversion Attack -->
837
+ <div id="inversion-content" class="attack-content">
838
+ <div class="attack-section">
839
+ <div class="attack-title">
840
+ <div class="attack-icon">🔄</div>
841
+ <div>
842
+ <h2>Model Inversion Attack</h2>
843
+ <p>Extract representative features for each class</p>
844
+ </div>
845
+ </div>
846
+
847
+ <div class="info-box">
848
+ <strong>Attack Goal:</strong> Generate synthetic data that represents what the model learned about each class, potentially revealing sensitive attributes.
849
+ </div>
850
+
851
+ <div class="attack-demo">
852
+ <div class="demo-panel">
853
+ <h3>Inversion Parameters</h3>
854
+ <div class="demo-controls">
855
+ <label>Target Class: <span id="inversion-class">Digit 7</span></label>
856
+ <select id="inversion-class-select" class="parameter-select">
857
+ <option value="0">Digit 0</option>
858
+ <option value="1">Digit 1</option>
859
+ <option value="7" selected>Digit 7</option>
860
+ <option value="9">Digit 9</option>
861
+ </select>
862
+
863
+ <label>Privacy Level: <span id="inversion-privacy">Medium</span></label>
864
+ <input type="range" class="demo-slider" id="inversion-privacy-slider" min="1" max="10" step="1" value="5">
865
+ </div>
866
+ <button class="control-button" onclick="runInversionAttack()">Generate Class Representative</button>
867
+ </div>
868
+
869
+ <div class="demo-panel">
870
+ <h3>Generated Features</h3>
871
+ <div class="visual-demo">
872
+ <div class="visual-item">
873
+ <div style="width: 120px; height: 120px; background: #e3f2fd; border-radius: 4px; margin: 0 auto 0.5rem; display: flex; align-items: center; justify-content: center; font-size: 3rem;">
874
+ 7
875
+ </div>
876
+ <div>Inverted Features</div>
877
+ <div style="font-size: 0.8rem; color: #666; margin-top: 0.5rem;">
878
+ Confidence: <span id="inversion-confidence">87%</span>
879
+ </div>
880
+ </div>
881
+ </div>
882
+ </div>
883
+ </div>
884
+ </div>
885
+ </div>
886
+
887
+ <!-- Property Inference Attack -->
888
+ <div id="property-content" class="attack-content">
889
+ <div class="attack-section">
890
+ <div class="attack-title">
891
+ <div class="attack-icon">📊</div>
892
+ <div>
893
+ <h2>Property Inference Attack</h2>
894
+ <p>Infer statistical properties of the training dataset</p>
895
+ </div>
896
+ </div>
897
+
898
+ <div class="warning-box">
899
+ <strong>Privacy Risk:</strong> Attackers can infer sensitive dataset properties like demographic distributions, even without seeing individual records.
900
+ </div>
901
+
902
+ <div class="attack-demo">
903
+ <div class="demo-panel">
904
+ <h3>Target Properties</h3>
905
+ <div class="demo-controls">
906
+ <label>Property Type:</label>
907
+ <select id="property-type" class="parameter-select">
908
+ <option value="gender">Gender Distribution</option>
909
+ <option value="age">Age Distribution</option>
910
+ <option value="location">Geographic Distribution</option>
911
+ </select>
912
+
913
+ <label>Model Access: <span id="property-access">Black-box</span></label>
914
+ <input type="range" class="demo-slider" id="property-access-slider" min="1" max="3" step="1" value="1">
915
+ </div>
916
+ <button class="control-button" onclick="runPropertyAttack()">Infer Properties</button>
917
+ </div>
918
+
919
+ <div class="demo-panel">
920
+ <h3>Inferred Properties</h3>
921
+ <div class="demo-result">
922
+ <div>Inferred Distribution:</div>
923
+ <div style="margin: 1rem 0;">
924
+ <div style="display: flex; justify-content: space-between; margin: 0.5rem 0;">
925
+ <span>Male:</span> <span id="property-male">52% ± 8%</span>
926
+ </div>
927
+ <div style="display: flex; justify-content: space-between; margin: 0.5rem 0;">
928
+ <span>Female:</span> <span id="property-female">48% ± 8%</span>
929
+ </div>
930
+ </div>
931
+ <div style="font-size: 0.8rem; color: #666;">
932
+ Confidence intervals show attack uncertainty
933
+ </div>
934
+ </div>
935
+ </div>
936
+ </div>
937
+
938
+ <div class="chart-container">
939
+ <canvas id="property-chart"></canvas>
940
+ </div>
941
+ </div>
942
+ </div>
943
+
944
+ <!-- Linkage Attack -->
945
+ <div id="linkage-content" class="attack-content">
946
+ <div class="attack-section">
947
+ <div class="attack-title">
948
+ <div class="attack-icon">🔗</div>
949
+ <div>
950
+ <h2>Linkage Attack</h2>
951
+ <p>Combine model outputs with auxiliary data sources</p>
952
+ </div>
953
+ </div>
954
+
955
+ <div class="warning-box">
956
+ <strong>Advanced Threat:</strong> Attackers combine model predictions with external datasets (social media, public records) to identify individuals and infer sensitive attributes.
957
+ </div>
958
+
959
+ <div class="linkage-demo">
960
+ <div class="linkage-source">
961
+ <h4>Model Outputs</h4>
962
+ <div>• Prediction scores</div>
963
+ <div>• Confidence levels</div>
964
+ <div>• Feature importance</div>
965
+ </div>
966
+
967
+ <div class="linkage-arrow">+</div>
968
+
969
+ <div class="linkage-source">
970
+ <h4>Auxiliary Data</h4>
971
+ <div>• Public records</div>
972
+ <div>• Social media</div>
973
+ <div>• Purchase history</div>
974
+ </div>
975
+
976
+ <div class="linkage-arrow">→</div>
977
+
978
+ <div class="linkage-source">
979
+ <h4>Linked Profile</h4>
980
+ <div>• Identity revealed</div>
981
+ <div>• Sensitive attributes</div>
982
+ <div>• Behavioral patterns</div>
983
+ </div>
984
+ </div>
985
+
986
+ <div class="attack-demo">
987
+ <div class="demo-panel">
988
+ <h3>Linkage Scenario</h3>
989
+ <div class="demo-controls">
990
+ <label>Auxiliary Data Quality: <span id="linkage-quality">High</span></label>
991
+ <input type="range" class="demo-slider" id="linkage-quality-slider" min="1" max="5" step="1" value="4">
992
+
993
+ <label>Model Privacy: <span id="linkage-model-privacy">Low (ε=8.0)</span></label>
994
+ <input type="range" class="demo-slider" id="linkage-privacy-slider" min="1" max="10" step="1" value="8">
995
+ </div>
996
+ <button class="control-button" onclick="runLinkageAttack()">Simulate Linkage</button>
997
+ </div>
998
+
999
+ <div class="demo-panel">
1000
+ <h3>Linkage Success</h3>
1001
+ <div class="demo-result">
1002
+ <div>Successful Links: <span class="success-rate" id="linkage-success">68%</span></div>
1003
+ <div>Confidence: <span id="linkage-confidence">High</span></div>
1004
+ <div style="margin-top: 1rem; font-size: 0.9rem;">
1005
+ <div>• 340 individuals identified</div>
1006
+ <div>• 89% attribute accuracy</div>
1007
+ <div>• 12% false positives</div>
1008
+ </div>
1009
+ </div>
1010
+ </div>
1011
+ </div>
1012
+
1013
+ <div class="chart-container">
1014
+ <canvas id="linkage-chart"></canvas>
1015
+ </div>
1016
+ </div>
1017
+ </div>
1018
+
1019
+ <!-- Attack Comparison -->
1020
+ <div id="comparison-content" class="attack-content">
1021
+ <div class="attack-section">
1022
+ <div class="attack-title">
1023
+ <div class="attack-icon">⚖️</div>
1024
+ <div>
1025
+ <h2>Attack Effectiveness Comparison</h2>
1026
+ <p>How different privacy levels affect attack success rates</p>
1027
+ </div>
1028
+ </div>
1029
+
1030
+ <div class="comparison-grid">
1031
+ <div class="comparison-card">
1032
+ <h3>No Privacy (ε = ∞)</h3>
1033
+ <div class="comparison-value" style="color: #d32f2f;">85%</div>
1034
+ <div>Average Attack Success</div>
1035
+ </div>
1036
+ <div class="comparison-card">
1037
+ <h3>Low Privacy (ε = 8.0)</h3>
1038
+ <div class="comparison-value" style="color: #f57c00;">72%</div>
1039
+ <div>Average Attack Success</div>
1040
+ </div>
1041
+ <div class="comparison-card">
1042
+ <h3>Medium Privacy (ε = 3.0)</h3>
1043
+ <div class="comparison-value" style="color: #fbc02d;">58%</div>
1044
+ <div>Average Attack Success</div>
1045
+ </div>
1046
+ <div class="comparison-card">
1047
+ <h3>High Privacy (ε = 1.0)</h3>
1048
+ <div class="comparison-value" style="color: #2e7d32;">42%</div>
1049
+ <div>Average Attack Success</div>
1050
+ </div>
1051
+ </div>
1052
+
1053
+ <div class="chart-container">
1054
+ <canvas id="comparison-chart"></canvas>
1055
+ </div>
1056
+
1057
+ <div class="info-box">
1058
+ <strong>Key Insight:</strong> As privacy budget (ε) decreases, attack success rates drop significantly. DP-SGD provides measurable protection against all attack types.
1059
+ </div>
1060
+ </div>
1061
+ </div>
1062
+
1063
+ <!-- Defense Mechanisms -->
1064
+ <div class="defense-section">
1065
+ <h2>🛡️ How DP-SGD Defends Against These Attacks</h2>
1066
+ <p>Differential privacy provides mathematical guarantees against all these attack types</p>
1067
+
1068
+ <div class="defense-grid">
1069
+ <div class="defense-item">
1070
+ <h3>Gradient Noise</h3>
1071
+ <p>Adds calibrated noise to gradients, making it impossible to perfectly reconstruct training data or infer membership with certainty.</p>
1072
+ </div>
1073
+ <div class="defense-item">
1074
+ <h3>Gradient Clipping</h3>
1075
+ <p>Limits the influence of any single training example, preventing attackers from identifying outliers or high-influence samples.</p>
1076
+ </div>
1077
+ <div class="defense-item">
1078
+ <h3>Privacy Accounting</h3>
1079
+ <p>Tracks cumulative privacy loss across training, ensuring mathematical bounds on what attackers can learn.</p>
1080
+ </div>
1081
+ <div class="defense-item">
1082
+ <h3>Composition Guarantees</h3>
1083
+ <p>Provides formal bounds even when multiple attacks are combined, protecting against sophisticated adversaries.</p>
1084
+ </div>
1085
+ </div>
1086
+ </div>
1087
+ </div>
1088
+ {% endblock %}
1089
+
1090
+ {% block extra_scripts %}
1091
+ <script src="{{ url_for('static', filename='js/attacks.js') }}"></script>
1092
+ {% endblock %}
app/templates/base.html CHANGED
@@ -24,6 +24,7 @@
24
  </div>
25
  <nav>
26
  <ul class="nav-list">
 
27
  <li><a href="{{ url_for('main.learning') }}" class="nav-link {% if request.endpoint == 'main.learning' %}active{% endif %}">Learning Hub</a></li>
28
  <li><a href="{{ url_for('main.index') }}" class="nav-link {% if request.endpoint == 'main.index' %}active{% endif %}">Playground</a></li>
29
  </ul>
 
24
  </div>
25
  <nav>
26
  <ul class="nav-list">
27
+ <li><a href="{{ url_for('main.attacks') }}" class="nav-link {% if request.endpoint == 'main.attacks' %}active{% endif %}">Privacy Attacks</a></li>
28
  <li><a href="{{ url_for('main.learning') }}" class="nav-link {% if request.endpoint == 'main.learning' %}active{% endif %}">Learning Hub</a></li>
29
  <li><a href="{{ url_for('main.index') }}" class="nav-link {% if request.endpoint == 'main.index' %}active{% endif %}">Playground</a></li>
30
  </ul>