moderne-visualizations-misc 0.76.0__py3-none-any.whl → 1.0.0__py3-none-any.whl

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.
@@ -1,1567 +1,1567 @@
1
1
  {
2
- "cells": [
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": 3,
6
+ "metadata": {
7
+ "tags": [
8
+ "parameters"
9
+ ]
10
+ },
11
+ "outputs": [],
12
+ "source": [
13
+ "repository_filter: list[str] = []"
14
+ ]
15
+ },
16
+ {
17
+ "cell_type": "code",
18
+ "execution_count": null,
19
+ "metadata": {},
20
+ "outputs": [
21
+ {
22
+ "data": {
23
+ "application/vnd.plotly.v1+json": {
24
+ "config": {
25
+ "plotlyServerURL": "https://plot.ly"
26
+ },
27
+ "data": [
3
28
  {
4
- "cell_type": "code",
5
- "execution_count": 3,
6
- "metadata": {
7
- "tags": [
8
- "parameters"
9
- ]
10
- },
11
- "outputs": [],
12
- "source": [
13
- "repository_filter: list[str] = []"
14
- ]
29
+ "customdata": [
30
+ {
31
+ "category_pct": 0.1,
32
+ "total_pct": 0
33
+ },
34
+ {
35
+ "category_pct": 0,
36
+ "total_pct": 0
37
+ },
38
+ {
39
+ "category_pct": 1.2,
40
+ "total_pct": 0.1
41
+ },
42
+ {
43
+ "category_pct": 0.5,
44
+ "total_pct": 0.1
45
+ }
46
+ ],
47
+ "hovertemplate": "<b>%{x}</b><br>Low (Direct): %{y}<br>Percent of %{x}: %{customdata.category_pct}%<br>Percent of all: %{customdata.total_pct}%<extra></extra>",
48
+ "legendgroup": "Low",
49
+ "marker": {
50
+ "color": "#52BBA0"
51
+ },
52
+ "name": "Low",
53
+ "showlegend": true,
54
+ "type": "bar",
55
+ "x": [
56
+ -0.2,
57
+ 0.8,
58
+ 1.8,
59
+ 2.8
60
+ ],
61
+ "y": [
62
+ 5,
63
+ 0,
64
+ 13,
65
+ 10
66
+ ]
15
67
  },
16
68
  {
17
- "cell_type": "code",
18
- "execution_count": null,
19
- "metadata": {},
20
- "outputs": [
21
- {
22
- "data": {
23
- "application/vnd.plotly.v1+json": {
24
- "config": {
25
- "plotlyServerURL": "https://plot.ly"
26
- },
27
- "data": [
28
- {
29
- "customdata": [
30
- {
31
- "category_pct": 0.1,
32
- "total_pct": 0
33
- },
34
- {
35
- "category_pct": 0,
36
- "total_pct": 0
37
- },
38
- {
39
- "category_pct": 1.2,
40
- "total_pct": 0.1
41
- },
42
- {
43
- "category_pct": 0.5,
44
- "total_pct": 0.1
45
- }
46
- ],
47
- "hovertemplate": "<b>%{x}</b><br>Low (Direct): %{y}<br>Percent of %{x}: %{customdata.category_pct}%<br>Percent of all: %{customdata.total_pct}%<extra></extra>",
48
- "legendgroup": "Low",
49
- "marker": {
50
- "color": "#52BBA0"
51
- },
52
- "name": "Low",
53
- "showlegend": true,
54
- "type": "bar",
55
- "x": [
56
- -0.2,
57
- 0.8,
58
- 1.8,
59
- 2.8
60
- ],
61
- "y": [
62
- 5,
63
- 0,
64
- 13,
65
- 10
66
- ]
67
- },
68
- {
69
- "customdata": [
70
- {
71
- "category_pct": 0.6,
72
- "total_pct": 0.3
73
- },
74
- {
75
- "category_pct": 2.3,
76
- "total_pct": 0.6
77
- },
78
- {
79
- "category_pct": 7.1,
80
- "total_pct": 0.5
81
- },
82
- {
83
- "category_pct": 2.2,
84
- "total_pct": 0.3
85
- }
86
- ],
87
- "hovertemplate": "<b>%{x}</b><br>Moderate (Direct): %{y}<br>Percent of %{x}: %{customdata.category_pct}%<br>Percent of all: %{customdata.total_pct}%<extra></extra>",
88
- "legendgroup": "Moderate",
89
- "marker": {
90
- "color": "#FEE968"
91
- },
92
- "name": "Moderate",
93
- "showlegend": true,
94
- "type": "bar",
95
- "x": [
96
- -0.2,
97
- 0.8,
98
- 1.8,
99
- 2.8
100
- ],
101
- "y": [
102
- 49,
103
- 87,
104
- 80,
105
- 40
106
- ]
107
- },
108
- {
109
- "customdata": [
110
- {
111
- "category_pct": 1,
112
- "total_pct": 0.5
113
- },
114
- {
115
- "category_pct": 3,
116
- "total_pct": 0.8
117
- },
118
- {
119
- "category_pct": 3.7,
120
- "total_pct": 0.3
121
- },
122
- {
123
- "category_pct": 0.9,
124
- "total_pct": 0.1
125
- }
126
- ],
127
- "hovertemplate": "<b>%{x}</b><br>High (Direct): %{y}<br>Percent of %{x}: %{customdata.category_pct}%<br>Percent of all: %{customdata.total_pct}%<extra></extra>",
128
- "legendgroup": "High",
129
- "marker": {
130
- "color": "#FABA49"
131
- },
132
- "name": "High",
133
- "showlegend": true,
134
- "type": "bar",
135
- "x": [
136
- -0.2,
137
- 0.8,
138
- 1.8,
139
- 2.8
140
- ],
141
- "y": [
142
- 78,
143
- 115,
144
- 42,
145
- 17
146
- ]
147
- },
148
- {
149
- "customdata": [
150
- {
151
- "category_pct": 0.3,
152
- "total_pct": 0.2
153
- },
154
- {
155
- "category_pct": 2.1,
156
- "total_pct": 0.5
157
- },
158
- {
159
- "category_pct": 4.9,
160
- "total_pct": 0.4
161
- },
162
- {
163
- "category_pct": 0.3,
164
- "total_pct": 0
165
- }
166
- ],
167
- "hovertemplate": "<b>%{x}</b><br>Critical (Direct): %{y}<br>Percent of %{x}: %{customdata.category_pct}%<br>Percent of all: %{customdata.total_pct}%<extra></extra>",
168
- "legendgroup": "Critical",
169
- "marker": {
170
- "color": "#FF5B5B"
171
- },
172
- "name": "Critical",
173
- "showlegend": true,
174
- "type": "bar",
175
- "x": [
176
- -0.2,
177
- 0.8,
178
- 1.8,
179
- 2.8
180
- ],
181
- "y": [
182
- 26,
183
- 81,
184
- 55,
185
- 5
186
- ]
187
- },
188
- {
189
- "customdata": [
190
- {
191
- "category_pct": 8,
192
- "total_pct": 4.4
193
- },
194
- {
195
- "category_pct": 6.5,
196
- "total_pct": 1.7
197
- },
198
- {
199
- "category_pct": 7.8,
200
- "total_pct": 0.6
201
- },
202
- {
203
- "category_pct": 14.6,
204
- "total_pct": 1.8
205
- }
206
- ],
207
- "hovertemplate": "<b>%{x}</b><br>Low (Transitive): %{y}<br>Percent of %{x}: %{customdata.category_pct}%<br>Percent of all: %{customdata.total_pct}%<extra></extra>",
208
- "legendgroup": "Low",
209
- "marker": {
210
- "color": "#52BBA0",
211
- "pattern": {
212
- "shape": "/"
213
- }
214
- },
215
- "name": "Low ",
216
- "showlegend": false,
217
- "type": "bar",
218
- "x": [
219
- 0.2,
220
- 1.2,
221
- 2.2,
222
- 3.2
223
- ],
224
- "y": [
225
- 650,
226
- 251,
227
- 87,
228
- 269
229
- ]
230
- },
231
- {
232
- "customdata": [
233
- {
234
- "category_pct": 37.6,
235
- "total_pct": 20.4
236
- },
237
- {
238
- "category_pct": 29.4,
239
- "total_pct": 7.6
240
- },
241
- {
242
- "category_pct": 31.6,
243
- "total_pct": 2.4
244
- },
245
- {
246
- "category_pct": 43.2,
247
- "total_pct": 5.3
248
- }
249
- ],
250
- "hovertemplate": "<b>%{x}</b><br>Moderate (Transitive): %{y}<br>Percent of %{x}: %{customdata.category_pct}%<br>Percent of all: %{customdata.total_pct}%<extra></extra>",
251
- "legendgroup": "Moderate",
252
- "marker": {
253
- "color": "#FEE968",
254
- "pattern": {
255
- "shape": "/"
256
- }
257
- },
258
- "name": "Moderate ",
259
- "showlegend": false,
260
- "type": "bar",
261
- "x": [
262
- 0.2,
263
- 1.2,
264
- 2.2,
265
- 3.2
266
- ],
267
- "y": [
268
- 3041,
269
- 1133,
270
- 355,
271
- 797
272
- ]
273
- },
274
- {
275
- "customdata": [
276
- {
277
- "category_pct": 42.8,
278
- "total_pct": 23.2
279
- },
280
- {
281
- "category_pct": 45,
282
- "total_pct": 11.6
283
- },
284
- {
285
- "category_pct": 29.1,
286
- "total_pct": 2.2
287
- },
288
- {
289
- "category_pct": 29.5,
290
- "total_pct": 3.7
291
- }
292
- ],
293
- "hovertemplate": "<b>%{x}</b><br>High (Transitive): %{y}<br>Percent of %{x}: %{customdata.category_pct}%<br>Percent of all: %{customdata.total_pct}%<extra></extra>",
294
- "legendgroup": "High",
295
- "marker": {
296
- "color": "#FABA49",
297
- "pattern": {
298
- "shape": "/"
299
- }
300
- },
301
- "name": "High ",
302
- "showlegend": false,
303
- "type": "bar",
304
- "x": [
305
- 0.2,
306
- 1.2,
307
- 2.2,
308
- 3.2
309
- ],
310
- "y": [
311
- 3467,
312
- 1734,
313
- 326,
314
- 545
315
- ]
316
- },
317
- {
318
- "customdata": [
319
- {
320
- "category_pct": 9.6,
321
- "total_pct": 5.2
322
- },
323
- {
324
- "category_pct": 11.8,
325
- "total_pct": 3
326
- },
327
- {
328
- "category_pct": 14.6,
329
- "total_pct": 1.1
330
- },
331
- {
332
- "category_pct": 8.8,
333
- "total_pct": 1.1
334
- }
335
- ],
336
- "hovertemplate": "<b>%{x}</b><br>Critical (Transitive): %{y}<br>Percent of %{x}: %{customdata.category_pct}%<br>Percent of all: %{customdata.total_pct}%<extra></extra>",
337
- "legendgroup": "Critical",
338
- "marker": {
339
- "color": "#FF5B5B",
340
- "pattern": {
341
- "shape": "/"
342
- }
343
- },
344
- "name": "Critical ",
345
- "showlegend": false,
346
- "type": "bar",
347
- "x": [
348
- 0.2,
349
- 1.2,
350
- 2.2,
351
- 3.2
352
- ],
353
- "y": [
354
- 778,
355
- 453,
356
- 164,
357
- 163
358
- ]
359
- }
360
- ],
361
- "layout": {
362
- "annotations": [
363
- {
364
- "font": {
365
- "size": 14
366
- },
367
- "showarrow": false,
368
- "text": "<b>Dependency Vulnerabilities by Fix Type</b>",
369
- "x": 0.5,
370
- "xref": "paper",
371
- "y": 1.05,
372
- "yref": "paper"
373
- }
374
- ],
375
- "bargap": 0.6,
376
- "bargroupgap": 0.1,
377
- "barmode": "stack",
378
- "legend": {
379
- "orientation": "v",
380
- "title": {
381
- "font": {
382
- "size": 12
383
- },
384
- "text": "Severity Level<br><sub>Solid: Direct | Striped: Transitive</sub>"
385
- },
386
- "traceorder": "reversed",
387
- "x": 1.02,
388
- "xanchor": "left",
389
- "y": 0.95,
390
- "yanchor": "top"
391
- },
392
- "margin": {
393
- "b": 60,
394
- "l": 0,
395
- "r": 0,
396
- "t": 60
397
- },
398
- "template": {
399
- "data": {
400
- "bar": [
401
- {
402
- "error_x": {
403
- "color": "#2a3f5f"
404
- },
405
- "error_y": {
406
- "color": "#2a3f5f"
407
- },
408
- "marker": {
409
- "line": {
410
- "color": "#E5ECF6",
411
- "width": 0.5
412
- },
413
- "pattern": {
414
- "fillmode": "overlay",
415
- "size": 10,
416
- "solidity": 0.2
417
- }
418
- },
419
- "type": "bar"
420
- }
421
- ],
422
- "barpolar": [
423
- {
424
- "marker": {
425
- "line": {
426
- "color": "#E5ECF6",
427
- "width": 0.5
428
- },
429
- "pattern": {
430
- "fillmode": "overlay",
431
- "size": 10,
432
- "solidity": 0.2
433
- }
434
- },
435
- "type": "barpolar"
436
- }
437
- ],
438
- "carpet": [
439
- {
440
- "aaxis": {
441
- "endlinecolor": "#2a3f5f",
442
- "gridcolor": "white",
443
- "linecolor": "white",
444
- "minorgridcolor": "white",
445
- "startlinecolor": "#2a3f5f"
446
- },
447
- "baxis": {
448
- "endlinecolor": "#2a3f5f",
449
- "gridcolor": "white",
450
- "linecolor": "white",
451
- "minorgridcolor": "white",
452
- "startlinecolor": "#2a3f5f"
453
- },
454
- "type": "carpet"
455
- }
456
- ],
457
- "choropleth": [
458
- {
459
- "colorbar": {
460
- "outlinewidth": 0,
461
- "ticks": ""
462
- },
463
- "type": "choropleth"
464
- }
465
- ],
466
- "contour": [
467
- {
468
- "colorbar": {
469
- "outlinewidth": 0,
470
- "ticks": ""
471
- },
472
- "colorscale": [
473
- [
474
- 0,
475
- "#0d0887"
476
- ],
477
- [
478
- 0.1111111111111111,
479
- "#46039f"
480
- ],
481
- [
482
- 0.2222222222222222,
483
- "#7201a8"
484
- ],
485
- [
486
- 0.3333333333333333,
487
- "#9c179e"
488
- ],
489
- [
490
- 0.4444444444444444,
491
- "#bd3786"
492
- ],
493
- [
494
- 0.5555555555555556,
495
- "#d8576b"
496
- ],
497
- [
498
- 0.6666666666666666,
499
- "#ed7953"
500
- ],
501
- [
502
- 0.7777777777777778,
503
- "#fb9f3a"
504
- ],
505
- [
506
- 0.8888888888888888,
507
- "#fdca26"
508
- ],
509
- [
510
- 1,
511
- "#f0f921"
512
- ]
513
- ],
514
- "type": "contour"
515
- }
516
- ],
517
- "contourcarpet": [
518
- {
519
- "colorbar": {
520
- "outlinewidth": 0,
521
- "ticks": ""
522
- },
523
- "type": "contourcarpet"
524
- }
525
- ],
526
- "heatmap": [
527
- {
528
- "colorbar": {
529
- "outlinewidth": 0,
530
- "ticks": ""
531
- },
532
- "colorscale": [
533
- [
534
- 0,
535
- "#0d0887"
536
- ],
537
- [
538
- 0.1111111111111111,
539
- "#46039f"
540
- ],
541
- [
542
- 0.2222222222222222,
543
- "#7201a8"
544
- ],
545
- [
546
- 0.3333333333333333,
547
- "#9c179e"
548
- ],
549
- [
550
- 0.4444444444444444,
551
- "#bd3786"
552
- ],
553
- [
554
- 0.5555555555555556,
555
- "#d8576b"
556
- ],
557
- [
558
- 0.6666666666666666,
559
- "#ed7953"
560
- ],
561
- [
562
- 0.7777777777777778,
563
- "#fb9f3a"
564
- ],
565
- [
566
- 0.8888888888888888,
567
- "#fdca26"
568
- ],
569
- [
570
- 1,
571
- "#f0f921"
572
- ]
573
- ],
574
- "type": "heatmap"
575
- }
576
- ],
577
- "heatmapgl": [
578
- {
579
- "colorbar": {
580
- "outlinewidth": 0,
581
- "ticks": ""
582
- },
583
- "colorscale": [
584
- [
585
- 0,
586
- "#0d0887"
587
- ],
588
- [
589
- 0.1111111111111111,
590
- "#46039f"
591
- ],
592
- [
593
- 0.2222222222222222,
594
- "#7201a8"
595
- ],
596
- [
597
- 0.3333333333333333,
598
- "#9c179e"
599
- ],
600
- [
601
- 0.4444444444444444,
602
- "#bd3786"
603
- ],
604
- [
605
- 0.5555555555555556,
606
- "#d8576b"
607
- ],
608
- [
609
- 0.6666666666666666,
610
- "#ed7953"
611
- ],
612
- [
613
- 0.7777777777777778,
614
- "#fb9f3a"
615
- ],
616
- [
617
- 0.8888888888888888,
618
- "#fdca26"
619
- ],
620
- [
621
- 1,
622
- "#f0f921"
623
- ]
624
- ],
625
- "type": "heatmapgl"
626
- }
627
- ],
628
- "histogram": [
629
- {
630
- "marker": {
631
- "pattern": {
632
- "fillmode": "overlay",
633
- "size": 10,
634
- "solidity": 0.2
635
- }
636
- },
637
- "type": "histogram"
638
- }
639
- ],
640
- "histogram2d": [
641
- {
642
- "colorbar": {
643
- "outlinewidth": 0,
644
- "ticks": ""
645
- },
646
- "colorscale": [
647
- [
648
- 0,
649
- "#0d0887"
650
- ],
651
- [
652
- 0.1111111111111111,
653
- "#46039f"
654
- ],
655
- [
656
- 0.2222222222222222,
657
- "#7201a8"
658
- ],
659
- [
660
- 0.3333333333333333,
661
- "#9c179e"
662
- ],
663
- [
664
- 0.4444444444444444,
665
- "#bd3786"
666
- ],
667
- [
668
- 0.5555555555555556,
669
- "#d8576b"
670
- ],
671
- [
672
- 0.6666666666666666,
673
- "#ed7953"
674
- ],
675
- [
676
- 0.7777777777777778,
677
- "#fb9f3a"
678
- ],
679
- [
680
- 0.8888888888888888,
681
- "#fdca26"
682
- ],
683
- [
684
- 1,
685
- "#f0f921"
686
- ]
687
- ],
688
- "type": "histogram2d"
689
- }
690
- ],
691
- "histogram2dcontour": [
692
- {
693
- "colorbar": {
694
- "outlinewidth": 0,
695
- "ticks": ""
696
- },
697
- "colorscale": [
698
- [
699
- 0,
700
- "#0d0887"
701
- ],
702
- [
703
- 0.1111111111111111,
704
- "#46039f"
705
- ],
706
- [
707
- 0.2222222222222222,
708
- "#7201a8"
709
- ],
710
- [
711
- 0.3333333333333333,
712
- "#9c179e"
713
- ],
714
- [
715
- 0.4444444444444444,
716
- "#bd3786"
717
- ],
718
- [
719
- 0.5555555555555556,
720
- "#d8576b"
721
- ],
722
- [
723
- 0.6666666666666666,
724
- "#ed7953"
725
- ],
726
- [
727
- 0.7777777777777778,
728
- "#fb9f3a"
729
- ],
730
- [
731
- 0.8888888888888888,
732
- "#fdca26"
733
- ],
734
- [
735
- 1,
736
- "#f0f921"
737
- ]
738
- ],
739
- "type": "histogram2dcontour"
740
- }
741
- ],
742
- "mesh3d": [
743
- {
744
- "colorbar": {
745
- "outlinewidth": 0,
746
- "ticks": ""
747
- },
748
- "type": "mesh3d"
749
- }
750
- ],
751
- "parcoords": [
752
- {
753
- "line": {
754
- "colorbar": {
755
- "outlinewidth": 0,
756
- "ticks": ""
757
- }
758
- },
759
- "type": "parcoords"
760
- }
761
- ],
762
- "pie": [
763
- {
764
- "automargin": true,
765
- "type": "pie"
766
- }
767
- ],
768
- "scatter": [
769
- {
770
- "fillpattern": {
771
- "fillmode": "overlay",
772
- "size": 10,
773
- "solidity": 0.2
774
- },
775
- "type": "scatter"
776
- }
777
- ],
778
- "scatter3d": [
779
- {
780
- "line": {
781
- "colorbar": {
782
- "outlinewidth": 0,
783
- "ticks": ""
784
- }
785
- },
786
- "marker": {
787
- "colorbar": {
788
- "outlinewidth": 0,
789
- "ticks": ""
790
- }
791
- },
792
- "type": "scatter3d"
793
- }
794
- ],
795
- "scattercarpet": [
796
- {
797
- "marker": {
798
- "colorbar": {
799
- "outlinewidth": 0,
800
- "ticks": ""
801
- }
802
- },
803
- "type": "scattercarpet"
804
- }
805
- ],
806
- "scattergeo": [
807
- {
808
- "marker": {
809
- "colorbar": {
810
- "outlinewidth": 0,
811
- "ticks": ""
812
- }
813
- },
814
- "type": "scattergeo"
815
- }
816
- ],
817
- "scattergl": [
818
- {
819
- "marker": {
820
- "colorbar": {
821
- "outlinewidth": 0,
822
- "ticks": ""
823
- }
824
- },
825
- "type": "scattergl"
826
- }
827
- ],
828
- "scattermapbox": [
829
- {
830
- "marker": {
831
- "colorbar": {
832
- "outlinewidth": 0,
833
- "ticks": ""
834
- }
835
- },
836
- "type": "scattermapbox"
837
- }
838
- ],
839
- "scatterpolar": [
840
- {
841
- "marker": {
842
- "colorbar": {
843
- "outlinewidth": 0,
844
- "ticks": ""
845
- }
846
- },
847
- "type": "scatterpolar"
848
- }
849
- ],
850
- "scatterpolargl": [
851
- {
852
- "marker": {
853
- "colorbar": {
854
- "outlinewidth": 0,
855
- "ticks": ""
856
- }
857
- },
858
- "type": "scatterpolargl"
859
- }
860
- ],
861
- "scatterternary": [
862
- {
863
- "marker": {
864
- "colorbar": {
865
- "outlinewidth": 0,
866
- "ticks": ""
867
- }
868
- },
869
- "type": "scatterternary"
870
- }
871
- ],
872
- "surface": [
873
- {
874
- "colorbar": {
875
- "outlinewidth": 0,
876
- "ticks": ""
877
- },
878
- "colorscale": [
879
- [
880
- 0,
881
- "#0d0887"
882
- ],
883
- [
884
- 0.1111111111111111,
885
- "#46039f"
886
- ],
887
- [
888
- 0.2222222222222222,
889
- "#7201a8"
890
- ],
891
- [
892
- 0.3333333333333333,
893
- "#9c179e"
894
- ],
895
- [
896
- 0.4444444444444444,
897
- "#bd3786"
898
- ],
899
- [
900
- 0.5555555555555556,
901
- "#d8576b"
902
- ],
903
- [
904
- 0.6666666666666666,
905
- "#ed7953"
906
- ],
907
- [
908
- 0.7777777777777778,
909
- "#fb9f3a"
910
- ],
911
- [
912
- 0.8888888888888888,
913
- "#fdca26"
914
- ],
915
- [
916
- 1,
917
- "#f0f921"
918
- ]
919
- ],
920
- "type": "surface"
921
- }
922
- ],
923
- "table": [
924
- {
925
- "cells": {
926
- "fill": {
927
- "color": "#EBF0F8"
928
- },
929
- "line": {
930
- "color": "white"
931
- }
932
- },
933
- "header": {
934
- "fill": {
935
- "color": "#C8D4E3"
936
- },
937
- "line": {
938
- "color": "white"
939
- }
940
- },
941
- "type": "table"
942
- }
943
- ]
944
- },
945
- "layout": {
946
- "annotationdefaults": {
947
- "arrowcolor": "#2a3f5f",
948
- "arrowhead": 0,
949
- "arrowwidth": 1
950
- },
951
- "autotypenumbers": "strict",
952
- "coloraxis": {
953
- "colorbar": {
954
- "outlinewidth": 0,
955
- "ticks": ""
956
- }
957
- },
958
- "colorscale": {
959
- "diverging": [
960
- [
961
- 0,
962
- "#8e0152"
963
- ],
964
- [
965
- 0.1,
966
- "#c51b7d"
967
- ],
968
- [
969
- 0.2,
970
- "#de77ae"
971
- ],
972
- [
973
- 0.3,
974
- "#f1b6da"
975
- ],
976
- [
977
- 0.4,
978
- "#fde0ef"
979
- ],
980
- [
981
- 0.5,
982
- "#f7f7f7"
983
- ],
984
- [
985
- 0.6,
986
- "#e6f5d0"
987
- ],
988
- [
989
- 0.7,
990
- "#b8e186"
991
- ],
992
- [
993
- 0.8,
994
- "#7fbc41"
995
- ],
996
- [
997
- 0.9,
998
- "#4d9221"
999
- ],
1000
- [
1001
- 1,
1002
- "#276419"
1003
- ]
1004
- ],
1005
- "sequential": [
1006
- [
1007
- 0,
1008
- "#0d0887"
1009
- ],
1010
- [
1011
- 0.1111111111111111,
1012
- "#46039f"
1013
- ],
1014
- [
1015
- 0.2222222222222222,
1016
- "#7201a8"
1017
- ],
1018
- [
1019
- 0.3333333333333333,
1020
- "#9c179e"
1021
- ],
1022
- [
1023
- 0.4444444444444444,
1024
- "#bd3786"
1025
- ],
1026
- [
1027
- 0.5555555555555556,
1028
- "#d8576b"
1029
- ],
1030
- [
1031
- 0.6666666666666666,
1032
- "#ed7953"
1033
- ],
1034
- [
1035
- 0.7777777777777778,
1036
- "#fb9f3a"
1037
- ],
1038
- [
1039
- 0.8888888888888888,
1040
- "#fdca26"
1041
- ],
1042
- [
1043
- 1,
1044
- "#f0f921"
1045
- ]
1046
- ],
1047
- "sequentialminus": [
1048
- [
1049
- 0,
1050
- "#0d0887"
1051
- ],
1052
- [
1053
- 0.1111111111111111,
1054
- "#46039f"
1055
- ],
1056
- [
1057
- 0.2222222222222222,
1058
- "#7201a8"
1059
- ],
1060
- [
1061
- 0.3333333333333333,
1062
- "#9c179e"
1063
- ],
1064
- [
1065
- 0.4444444444444444,
1066
- "#bd3786"
1067
- ],
1068
- [
1069
- 0.5555555555555556,
1070
- "#d8576b"
1071
- ],
1072
- [
1073
- 0.6666666666666666,
1074
- "#ed7953"
1075
- ],
1076
- [
1077
- 0.7777777777777778,
1078
- "#fb9f3a"
1079
- ],
1080
- [
1081
- 0.8888888888888888,
1082
- "#fdca26"
1083
- ],
1084
- [
1085
- 1,
1086
- "#f0f921"
1087
- ]
1088
- ]
1089
- },
1090
- "colorway": [
1091
- "#636efa",
1092
- "#EF553B",
1093
- "#00cc96",
1094
- "#ab63fa",
1095
- "#FFA15A",
1096
- "#19d3f3",
1097
- "#FF6692",
1098
- "#B6E880",
1099
- "#FF97FF",
1100
- "#FECB52"
1101
- ],
1102
- "font": {
1103
- "color": "#2a3f5f"
1104
- },
1105
- "geo": {
1106
- "bgcolor": "white",
1107
- "lakecolor": "white",
1108
- "landcolor": "#E5ECF6",
1109
- "showlakes": true,
1110
- "showland": true,
1111
- "subunitcolor": "white"
1112
- },
1113
- "hoverlabel": {
1114
- "align": "left"
1115
- },
1116
- "hovermode": "closest",
1117
- "mapbox": {
1118
- "style": "light"
1119
- },
1120
- "paper_bgcolor": "white",
1121
- "plot_bgcolor": "#E5ECF6",
1122
- "polar": {
1123
- "angularaxis": {
1124
- "gridcolor": "white",
1125
- "linecolor": "white",
1126
- "ticks": ""
1127
- },
1128
- "bgcolor": "#E5ECF6",
1129
- "radialaxis": {
1130
- "gridcolor": "white",
1131
- "linecolor": "white",
1132
- "ticks": ""
1133
- }
1134
- },
1135
- "scene": {
1136
- "xaxis": {
1137
- "backgroundcolor": "#E5ECF6",
1138
- "gridcolor": "white",
1139
- "gridwidth": 2,
1140
- "linecolor": "white",
1141
- "showbackground": true,
1142
- "ticks": "",
1143
- "zerolinecolor": "white"
1144
- },
1145
- "yaxis": {
1146
- "backgroundcolor": "#E5ECF6",
1147
- "gridcolor": "white",
1148
- "gridwidth": 2,
1149
- "linecolor": "white",
1150
- "showbackground": true,
1151
- "ticks": "",
1152
- "zerolinecolor": "white"
1153
- },
1154
- "zaxis": {
1155
- "backgroundcolor": "#E5ECF6",
1156
- "gridcolor": "white",
1157
- "gridwidth": 2,
1158
- "linecolor": "white",
1159
- "showbackground": true,
1160
- "ticks": "",
1161
- "zerolinecolor": "white"
1162
- }
1163
- },
1164
- "shapedefaults": {
1165
- "line": {
1166
- "color": "#2a3f5f"
1167
- }
1168
- },
1169
- "ternary": {
1170
- "aaxis": {
1171
- "gridcolor": "white",
1172
- "linecolor": "white",
1173
- "ticks": ""
1174
- },
1175
- "baxis": {
1176
- "gridcolor": "white",
1177
- "linecolor": "white",
1178
- "ticks": ""
1179
- },
1180
- "bgcolor": "#E5ECF6",
1181
- "caxis": {
1182
- "gridcolor": "white",
1183
- "linecolor": "white",
1184
- "ticks": ""
1185
- }
1186
- },
1187
- "title": {
1188
- "x": 0.05
1189
- },
1190
- "xaxis": {
1191
- "automargin": true,
1192
- "gridcolor": "white",
1193
- "linecolor": "white",
1194
- "ticks": "",
1195
- "title": {
1196
- "standoff": 15
1197
- },
1198
- "zerolinecolor": "white",
1199
- "zerolinewidth": 2
1200
- },
1201
- "yaxis": {
1202
- "automargin": true,
1203
- "gridcolor": "white",
1204
- "linecolor": "white",
1205
- "ticks": "",
1206
- "title": {
1207
- "standoff": 15
1208
- },
1209
- "zerolinecolor": "white",
1210
- "zerolinewidth": 2
1211
- }
1212
- }
1213
- },
1214
- "xaxis": {
1215
- "tickmode": "array",
1216
- "ticktext": [
1217
- "Patch",
1218
- "Minor",
1219
- "Major",
1220
- "No fixed version"
1221
- ],
1222
- "tickvals": [
1223
- 0,
1224
- 1,
1225
- 2,
1226
- 3
1227
- ],
1228
- "title": {
1229
- "text": "Type of version required to fix vulnerability"
1230
- }
1231
- },
1232
- "yaxis": {
1233
- "title": {
1234
- "text": "Vulnerability count"
1235
- }
1236
- }
1237
- }
1238
- }
1239
- },
1240
- "metadata": {},
1241
- "output_type": "display_data"
1242
- }
1243
- ],
1244
- "source": [
1245
- "import pandas as pd\n",
1246
- "import warnings\n",
1247
- "import plotly.graph_objects as go\n",
1248
- "import code_data_science.data_table as dt\n",
1249
- "\n",
1250
- "warnings.simplefilter(\"ignore\")\n",
1251
- "\n",
1252
- "df = dt.read_csv(\"../samples/dependency_vulnerabilities.csv\")\n",
1253
- "\n",
1254
- "df[\"repositoryWithBranch\"] = df[\"repositoryPath\"] + \"/\" + df[\"repositoryBranch\"]\n",
1255
- "\n",
1256
- "# Filter the data frame to only include rows where repositoryWithBranch contain\n",
1257
- "# a term in the repository_filter (case insensitive)\n",
1258
- "if len(repository_filter) > 0:\n",
1259
- " df = df[\n",
1260
- " df[\"repositoryWithBranch\"].str.contains(\"|\".join(repository_filter), case=False)\n",
1261
- " ]\n",
1262
- "\n",
1263
- "\n",
1264
- "def create_bar_plot(df_direct, df_transitive):\n",
1265
- " if df_direct is None or df_transitive is None:\n",
1266
- " # Create empty dataframes with the correct structure\n",
1267
- " fix_types = [\"Patch\", \"Minor\", \"Major\", \"No fixed version\"]\n",
1268
- " df_direct = pd.DataFrame(\n",
1269
- " {\n",
1270
- " \"Type\": fix_types,\n",
1271
- " \"Low\": [0] * 4,\n",
1272
- " \"Moderate\": [0] * 4,\n",
1273
- " \"High\": [0] * 4,\n",
1274
- " \"Critical\": [0] * 4,\n",
1275
- " }\n",
1276
- " )\n",
1277
- " df_transitive = pd.DataFrame(\n",
1278
- " {\n",
1279
- " \"Type\": fix_types,\n",
1280
- " \"Low\": [0] * 4,\n",
1281
- " \"Moderate\": [0] * 4,\n",
1282
- " \"High\": [0] * 4,\n",
1283
- " \"Critical\": [0] * 4,\n",
1284
- " }\n",
1285
- " )\n",
1286
- "\n",
1287
- " fig = go.Figure()\n",
1288
- "\n",
1289
- " # Define colors for severity levels\n",
1290
- " colors = {\n",
1291
- " \"Critical\": \"#FF5B5B\",\n",
1292
- " \"High\": \"#FABA49\",\n",
1293
- " \"Moderate\": \"#FEE968\",\n",
1294
- " \"Low\": \"#52BBA0\",\n",
1295
- " }\n",
1296
- "\n",
1297
- " # Calculate totals for percentage calculations\n",
1298
- " df_direct[\"Total\"] = df_direct[[\"Critical\", \"High\", \"Moderate\", \"Low\"]].sum(axis=1)\n",
1299
- " df_transitive[\"Total\"] = df_transitive[[\"Critical\", \"High\", \"Moderate\", \"Low\"]].sum(\n",
1300
- " axis=1\n",
1301
- " )\n",
1302
- " grand_total = df_direct[\"Total\"].sum() + df_transitive[\"Total\"].sum()\n",
1303
- "\n",
1304
- " # Create custom x-axis positions for grouping\n",
1305
- " fix_types = df_direct[\"Type\"].tolist()\n",
1306
- " n_groups = len(fix_types)\n",
1307
- " \n",
1308
- " # Create x positions: each group gets positions like [0, 0.4], [1, 1.4], [2, 2.4], etc.\n",
1309
- " x_direct = [i - 0.2 for i in range(n_groups)]\n",
1310
- " x_transitive = [i + 0.2 for i in range(n_groups)]\n",
1311
- " \n",
1312
- " # Custom tick labels and positions for the main groups\n",
1313
- " tick_positions = list(range(n_groups))\n",
1314
- " tick_labels = fix_types\n",
1315
- "\n",
1316
- " # Add traces for direct dependencies\n",
1317
- " for i, severity in enumerate([\"Low\", \"Moderate\", \"High\", \"Critical\"]):\n",
1318
- " # Calculate percentages for hover\n",
1319
- " percentages_direct = []\n",
1320
- " for idx in range(len(df_direct)):\n",
1321
- " count = df_direct.iloc[idx][severity]\n",
1322
- " total_in_category = (\n",
1323
- " df_direct.iloc[idx][\"Total\"] + df_transitive.iloc[idx][\"Total\"]\n",
1324
- " )\n",
1325
- " pct_of_category = (\n",
1326
- " (count / total_in_category * 100) if total_in_category > 0 else 0\n",
1327
- " )\n",
1328
- " pct_of_all = (count / grand_total * 100) if grand_total > 0 else 0\n",
1329
- " percentages_direct.append(\n",
1330
- " {\n",
1331
- " \"category_pct\": round(pct_of_category, 1),\n",
1332
- " \"total_pct\": round(pct_of_all, 1),\n",
1333
- " }\n",
1334
- " )\n",
1335
- "\n",
1336
- " fig.add_trace(\n",
1337
- " go.Bar(\n",
1338
- " name=severity,\n",
1339
- " x=x_direct,\n",
1340
- " y=df_direct[severity],\n",
1341
- " marker_color=colors[severity],\n",
1342
- " legendgroup=severity,\n",
1343
- " showlegend=True,\n",
1344
- " width=0.35, # Make bars wider\n",
1345
- " customdata=percentages_direct,\n",
1346
- " hovertemplate=(\n",
1347
- " \"<b>%{x}</b><br>\"\n",
1348
- " + f\"{severity} (Direct): %{{y}}<br>\"\n",
1349
- " + \"Percent of %{x}: %{customdata.category_pct}%<br>\"\n",
1350
- " + \"Percent of all: %{customdata.total_pct}%\"\n",
1351
- " + \"<extra></extra>\"\n",
1352
- " ),\n",
1353
- " )\n",
1354
- " )\n",
1355
- "\n",
1356
- " # Add traces for transitive dependencies\n",
1357
- " for i, severity in enumerate([\"Low\", \"Moderate\", \"High\", \"Critical\"]):\n",
1358
- " # Calculate percentages for hover\n",
1359
- " percentages_transitive = []\n",
1360
- " for idx in range(len(df_transitive)):\n",
1361
- " count = df_transitive.iloc[idx][severity]\n",
1362
- " total_in_category = (\n",
1363
- " df_direct.iloc[idx][\"Total\"] + df_transitive.iloc[idx][\"Total\"]\n",
1364
- " )\n",
1365
- " pct_of_category = (\n",
1366
- " (count / total_in_category * 100) if total_in_category > 0 else 0\n",
1367
- " )\n",
1368
- " pct_of_all = (count / grand_total * 100) if grand_total > 0 else 0\n",
1369
- " percentages_transitive.append(\n",
1370
- " {\n",
1371
- " \"category_pct\": round(pct_of_category, 1),\n",
1372
- " \"total_pct\": round(pct_of_all, 1),\n",
1373
- " }\n",
1374
- " )\n",
1375
- "\n",
1376
- " fig.add_trace(\n",
1377
- " go.Bar(\n",
1378
- " name=f\"{severity} \", # Add space to make it different from direct\n",
1379
- " x=x_transitive,\n",
1380
- " y=df_transitive[severity],\n",
1381
- " marker_color=colors[severity],\n",
1382
- " marker_pattern_shape=\"/\",\n",
1383
- " legendgroup=severity,\n",
1384
- " showlegend=False, # Hide from legend since we'll use annotations\n",
1385
- " width=0.35, # Make bars wider\n",
1386
- " customdata=percentages_transitive,\n",
1387
- " hovertemplate=(\n",
1388
- " \"<b>%{x}</b><br>\"\n",
1389
- " + f\"{severity} (Transitive): %{{y}}<br>\"\n",
1390
- " + \"Percent of %{x}: %{customdata.category_pct}%<br>\"\n",
1391
- " + \"Percent of all: %{customdata.total_pct}%\"\n",
1392
- " + \"<extra></extra>\"\n",
1393
- " ),\n",
1394
- " )\n",
1395
- " )\n",
1396
- "\n",
1397
- " # Update layout with improved legend\n",
1398
- " fig.update_layout(\n",
1399
- " xaxis={\n",
1400
- " \"title\": \"Type of version required to fix vulnerability\",\n",
1401
- " \"tickmode\": \"array\",\n",
1402
- " \"tickvals\": tick_positions,\n",
1403
- " \"ticktext\": tick_labels,\n",
1404
- " },\n",
1405
- " yaxis={\"title\": \"Vulnerability count\"},\n",
1406
- " barmode=\"stack\",\n",
1407
- " bargap=0.6, # Increase gap between groups\n",
1408
- " bargroupgap=0.1, # Small gap within groups\n",
1409
- " margin=dict(l=0, r=0, t=60, b=60),\n",
1410
- " legend=dict(\n",
1411
- " orientation=\"v\",\n",
1412
- " yanchor=\"top\",\n",
1413
- " y=0.95,\n",
1414
- " xanchor=\"left\",\n",
1415
- " x=1.02,\n",
1416
- " title=dict(\n",
1417
- " text=\"Severity Level<br><sub>Solid: Direct | Striped: Transitive</sub>\",\n",
1418
- " font=dict(size=12),\n",
1419
- " ),\n",
1420
- " traceorder=\"reversed\", # Reverse legend order to show Critical first\n",
1421
- " ),\n",
1422
- " annotations=[\n",
1423
- " dict(\n",
1424
- " text=\"<b>Dependency Vulnerabilities by Fix Type</b>\",\n",
1425
- " xref=\"paper\",\n",
1426
- " yref=\"paper\",\n",
1427
- " x=0.5,\n",
1428
- " y=1.05,\n",
1429
- " showarrow=False,\n",
1430
- " font=dict(size=14),\n",
1431
- " )\n",
1432
- " ],\n",
1433
- " )\n",
1434
- "\n",
1435
- " return fig\n",
1436
- "\n",
1437
- "\n",
1438
- "# Exit early if there are no stack traces and render a plot with a message\n",
1439
- "if len(df) == 0:\n",
1440
- " fig = create_bar_plot(None, None)\n",
1441
- " fig.update_yaxes(range=[0, 10])\n",
1442
- " fig.show(render=\"plotly_mimetype\")\n",
1443
- "else:\n",
1444
- "\n",
1445
- " def get_semver_fix(version, fixed_version):\n",
1446
- " \"\"\"\n",
1447
- " looks at current version and fixed version and determines if the fix is a major, minor, patch version, or no fix\n",
1448
- " \"\"\"\n",
1449
- " version_components = version.split(\".\")\n",
1450
- " fixed_components = fixed_version.split(\".\")\n",
1451
- "\n",
1452
- " # if fixed version is empty, return \"No fixed version\"\n",
1453
- " if fixed_version == \"\":\n",
1454
- " return \"No fixed version\"\n",
1455
- "\n",
1456
- " if len(version_components) < 3:\n",
1457
- " # fill in the missing version components with 0\n",
1458
- " for i in range(3 - len(version_components)):\n",
1459
- " version_components.append(\"0\")\n",
1460
- " if len(fixed_components) < 3:\n",
1461
- " # fill in the missing version components with 0\n",
1462
- " for i in range(3 - len(fixed_components)):\n",
1463
- " fixed_components.append(\"0\")\n",
1464
- "\n",
1465
- " elif version_components[0] != fixed_components[0]:\n",
1466
- " return \"Major\"\n",
1467
- " elif version_components[1] != fixed_components[1]:\n",
1468
- " return \"Minor\"\n",
1469
- " elif version_components[2] != fixed_components[2]:\n",
1470
- " return \"Patch\"\n",
1471
- " else:\n",
1472
- " return \"Unknown\"\n",
1473
- "\n",
1474
- " # drop unnecessary columns except depth which we need\n",
1475
- " df = df.drop(\n",
1476
- " columns=[\n",
1477
- " \"repositoryOrigin\",\n",
1478
- " \"repositoryPath\",\n",
1479
- " \"repositoryBranch\",\n",
1480
- " \"repositoryWithBranch\",\n",
1481
- " \"cve\",\n",
1482
- " \"groupId\",\n",
1483
- " \"artifactId\",\n",
1484
- " \"summary\",\n",
1485
- " ]\n",
1486
- " )\n",
1487
- "\n",
1488
- " # fill NaN values with empty string\n",
1489
- " df[\"fixedVersion\"] = df[\"fixedVersion\"].fillna(\"\")\n",
1490
- " df[\"version\"] = df[\"version\"].fillna(\"\")\n",
1491
- " # make sure version and fixedVersion is a string\n",
1492
- " df[\"fixedVersion\"] = df[\"fixedVersion\"].astype(str)\n",
1493
- " df[\"version\"] = df[\"version\"].astype(str)\n",
1494
- "\n",
1495
- " # add column 'semverFix' to dataframe\n",
1496
- " df[\"semverFix\"] = df.apply(\n",
1497
- " lambda x: get_semver_fix(x[\"version\"], x[\"fixedVersion\"]), axis=1\n",
1498
- " )\n",
1499
- "\n",
1500
- " # Split into direct and transitive\n",
1501
- " df_direct = df[df[\"depth\"] == 0]\n",
1502
- " df_transitive = df[df[\"depth\"] != 0]\n",
1503
- "\n",
1504
- " # Define the order for fix types\n",
1505
- " fix_order = [\"Patch\", \"Minor\", \"Major\", \"No fixed version\"]\n",
1506
- "\n",
1507
- " # Create aggregated data for direct dependencies\n",
1508
- " direct_data = []\n",
1509
- " for fix_type in fix_order:\n",
1510
- " fix_df = df_direct[df_direct[\"semverFix\"] == fix_type]\n",
1511
- " severity_counts = fix_df[\"severity\"].value_counts()\n",
1512
- " direct_data.append(\n",
1513
- " {\n",
1514
- " \"Type\": fix_type,\n",
1515
- " \"Critical\": severity_counts.get(\"CRITICAL\", 0),\n",
1516
- " \"High\": severity_counts.get(\"HIGH\", 0),\n",
1517
- " \"Moderate\": severity_counts.get(\"MODERATE\", 0),\n",
1518
- " \"Low\": severity_counts.get(\"LOW\", 0),\n",
1519
- " }\n",
1520
- " )\n",
1521
- " df_direct_plot = pd.DataFrame(direct_data)\n",
1522
- "\n",
1523
- " # Create aggregated data for transitive dependencies\n",
1524
- " transitive_data = []\n",
1525
- " for fix_type in fix_order:\n",
1526
- " fix_df = df_transitive[df_transitive[\"semverFix\"] == fix_type]\n",
1527
- " severity_counts = fix_df[\"severity\"].value_counts()\n",
1528
- " transitive_data.append(\n",
1529
- " {\n",
1530
- " \"Type\": fix_type,\n",
1531
- " \"Critical\": severity_counts.get(\"CRITICAL\", 0),\n",
1532
- " \"High\": severity_counts.get(\"HIGH\", 0),\n",
1533
- " \"Moderate\": severity_counts.get(\"MODERATE\", 0),\n",
1534
- " \"Low\": severity_counts.get(\"LOW\", 0),\n",
1535
- " }\n",
1536
- " )\n",
1537
- " df_transitive_plot = pd.DataFrame(transitive_data)\n",
1538
- "\n",
1539
- " fig = create_bar_plot(df_direct_plot, df_transitive_plot)\n",
1540
- "\n",
1541
- " # Show the figure\n",
1542
- " fig.show(render=\"plotly_mimetype\")"
1543
- ]
69
+ "customdata": [
70
+ {
71
+ "category_pct": 0.6,
72
+ "total_pct": 0.3
73
+ },
74
+ {
75
+ "category_pct": 2.3,
76
+ "total_pct": 0.6
77
+ },
78
+ {
79
+ "category_pct": 7.1,
80
+ "total_pct": 0.5
81
+ },
82
+ {
83
+ "category_pct": 2.2,
84
+ "total_pct": 0.3
85
+ }
86
+ ],
87
+ "hovertemplate": "<b>%{x}</b><br>Moderate (Direct): %{y}<br>Percent of %{x}: %{customdata.category_pct}%<br>Percent of all: %{customdata.total_pct}%<extra></extra>",
88
+ "legendgroup": "Moderate",
89
+ "marker": {
90
+ "color": "#FEE968"
91
+ },
92
+ "name": "Moderate",
93
+ "showlegend": true,
94
+ "type": "bar",
95
+ "x": [
96
+ -0.2,
97
+ 0.8,
98
+ 1.8,
99
+ 2.8
100
+ ],
101
+ "y": [
102
+ 49,
103
+ 87,
104
+ 80,
105
+ 40
106
+ ]
107
+ },
108
+ {
109
+ "customdata": [
110
+ {
111
+ "category_pct": 1,
112
+ "total_pct": 0.5
113
+ },
114
+ {
115
+ "category_pct": 3,
116
+ "total_pct": 0.8
117
+ },
118
+ {
119
+ "category_pct": 3.7,
120
+ "total_pct": 0.3
121
+ },
122
+ {
123
+ "category_pct": 0.9,
124
+ "total_pct": 0.1
125
+ }
126
+ ],
127
+ "hovertemplate": "<b>%{x}</b><br>High (Direct): %{y}<br>Percent of %{x}: %{customdata.category_pct}%<br>Percent of all: %{customdata.total_pct}%<extra></extra>",
128
+ "legendgroup": "High",
129
+ "marker": {
130
+ "color": "#FABA49"
131
+ },
132
+ "name": "High",
133
+ "showlegend": true,
134
+ "type": "bar",
135
+ "x": [
136
+ -0.2,
137
+ 0.8,
138
+ 1.8,
139
+ 2.8
140
+ ],
141
+ "y": [
142
+ 78,
143
+ 115,
144
+ 42,
145
+ 17
146
+ ]
147
+ },
148
+ {
149
+ "customdata": [
150
+ {
151
+ "category_pct": 0.3,
152
+ "total_pct": 0.2
153
+ },
154
+ {
155
+ "category_pct": 2.1,
156
+ "total_pct": 0.5
157
+ },
158
+ {
159
+ "category_pct": 4.9,
160
+ "total_pct": 0.4
161
+ },
162
+ {
163
+ "category_pct": 0.3,
164
+ "total_pct": 0
165
+ }
166
+ ],
167
+ "hovertemplate": "<b>%{x}</b><br>Critical (Direct): %{y}<br>Percent of %{x}: %{customdata.category_pct}%<br>Percent of all: %{customdata.total_pct}%<extra></extra>",
168
+ "legendgroup": "Critical",
169
+ "marker": {
170
+ "color": "#FF5B5B"
171
+ },
172
+ "name": "Critical",
173
+ "showlegend": true,
174
+ "type": "bar",
175
+ "x": [
176
+ -0.2,
177
+ 0.8,
178
+ 1.8,
179
+ 2.8
180
+ ],
181
+ "y": [
182
+ 26,
183
+ 81,
184
+ 55,
185
+ 5
186
+ ]
187
+ },
188
+ {
189
+ "customdata": [
190
+ {
191
+ "category_pct": 8,
192
+ "total_pct": 4.4
193
+ },
194
+ {
195
+ "category_pct": 6.5,
196
+ "total_pct": 1.7
197
+ },
198
+ {
199
+ "category_pct": 7.8,
200
+ "total_pct": 0.6
201
+ },
202
+ {
203
+ "category_pct": 14.6,
204
+ "total_pct": 1.8
205
+ }
206
+ ],
207
+ "hovertemplate": "<b>%{x}</b><br>Low (Transitive): %{y}<br>Percent of %{x}: %{customdata.category_pct}%<br>Percent of all: %{customdata.total_pct}%<extra></extra>",
208
+ "legendgroup": "Low",
209
+ "marker": {
210
+ "color": "#52BBA0",
211
+ "pattern": {
212
+ "shape": "/"
213
+ }
214
+ },
215
+ "name": "Low ",
216
+ "showlegend": false,
217
+ "type": "bar",
218
+ "x": [
219
+ 0.2,
220
+ 1.2,
221
+ 2.2,
222
+ 3.2
223
+ ],
224
+ "y": [
225
+ 650,
226
+ 251,
227
+ 87,
228
+ 269
229
+ ]
230
+ },
231
+ {
232
+ "customdata": [
233
+ {
234
+ "category_pct": 37.6,
235
+ "total_pct": 20.4
236
+ },
237
+ {
238
+ "category_pct": 29.4,
239
+ "total_pct": 7.6
240
+ },
241
+ {
242
+ "category_pct": 31.6,
243
+ "total_pct": 2.4
244
+ },
245
+ {
246
+ "category_pct": 43.2,
247
+ "total_pct": 5.3
248
+ }
249
+ ],
250
+ "hovertemplate": "<b>%{x}</b><br>Moderate (Transitive): %{y}<br>Percent of %{x}: %{customdata.category_pct}%<br>Percent of all: %{customdata.total_pct}%<extra></extra>",
251
+ "legendgroup": "Moderate",
252
+ "marker": {
253
+ "color": "#FEE968",
254
+ "pattern": {
255
+ "shape": "/"
256
+ }
257
+ },
258
+ "name": "Moderate ",
259
+ "showlegend": false,
260
+ "type": "bar",
261
+ "x": [
262
+ 0.2,
263
+ 1.2,
264
+ 2.2,
265
+ 3.2
266
+ ],
267
+ "y": [
268
+ 3041,
269
+ 1133,
270
+ 355,
271
+ 797
272
+ ]
273
+ },
274
+ {
275
+ "customdata": [
276
+ {
277
+ "category_pct": 42.8,
278
+ "total_pct": 23.2
279
+ },
280
+ {
281
+ "category_pct": 45,
282
+ "total_pct": 11.6
283
+ },
284
+ {
285
+ "category_pct": 29.1,
286
+ "total_pct": 2.2
287
+ },
288
+ {
289
+ "category_pct": 29.5,
290
+ "total_pct": 3.7
291
+ }
292
+ ],
293
+ "hovertemplate": "<b>%{x}</b><br>High (Transitive): %{y}<br>Percent of %{x}: %{customdata.category_pct}%<br>Percent of all: %{customdata.total_pct}%<extra></extra>",
294
+ "legendgroup": "High",
295
+ "marker": {
296
+ "color": "#FABA49",
297
+ "pattern": {
298
+ "shape": "/"
299
+ }
300
+ },
301
+ "name": "High ",
302
+ "showlegend": false,
303
+ "type": "bar",
304
+ "x": [
305
+ 0.2,
306
+ 1.2,
307
+ 2.2,
308
+ 3.2
309
+ ],
310
+ "y": [
311
+ 3467,
312
+ 1734,
313
+ 326,
314
+ 545
315
+ ]
316
+ },
317
+ {
318
+ "customdata": [
319
+ {
320
+ "category_pct": 9.6,
321
+ "total_pct": 5.2
322
+ },
323
+ {
324
+ "category_pct": 11.8,
325
+ "total_pct": 3
326
+ },
327
+ {
328
+ "category_pct": 14.6,
329
+ "total_pct": 1.1
330
+ },
331
+ {
332
+ "category_pct": 8.8,
333
+ "total_pct": 1.1
334
+ }
335
+ ],
336
+ "hovertemplate": "<b>%{x}</b><br>Critical (Transitive): %{y}<br>Percent of %{x}: %{customdata.category_pct}%<br>Percent of all: %{customdata.total_pct}%<extra></extra>",
337
+ "legendgroup": "Critical",
338
+ "marker": {
339
+ "color": "#FF5B5B",
340
+ "pattern": {
341
+ "shape": "/"
342
+ }
343
+ },
344
+ "name": "Critical ",
345
+ "showlegend": false,
346
+ "type": "bar",
347
+ "x": [
348
+ 0.2,
349
+ 1.2,
350
+ 2.2,
351
+ 3.2
352
+ ],
353
+ "y": [
354
+ 778,
355
+ 453,
356
+ 164,
357
+ 163
358
+ ]
1544
359
  }
1545
- ],
1546
- "metadata": {
1547
- "kernelspec": {
1548
- "display_name": ".venv",
1549
- "language": "python",
1550
- "name": "python3"
360
+ ],
361
+ "layout": {
362
+ "annotations": [
363
+ {
364
+ "font": {
365
+ "size": 14
366
+ },
367
+ "showarrow": false,
368
+ "text": "<b>Dependency Vulnerabilities by Fix Type</b>",
369
+ "x": 0.5,
370
+ "xref": "paper",
371
+ "y": 1.05,
372
+ "yref": "paper"
373
+ }
374
+ ],
375
+ "bargap": 0.6,
376
+ "bargroupgap": 0.1,
377
+ "barmode": "stack",
378
+ "legend": {
379
+ "orientation": "v",
380
+ "title": {
381
+ "font": {
382
+ "size": 12
383
+ },
384
+ "text": "Severity Level<br><sub>Solid: Direct | Striped: Transitive</sub>"
385
+ },
386
+ "traceorder": "reversed",
387
+ "x": 1.02,
388
+ "xanchor": "left",
389
+ "y": 0.95,
390
+ "yanchor": "top"
1551
391
  },
1552
- "language_info": {
1553
- "codemirror_mode": {
1554
- "name": "ipython",
1555
- "version": 3
392
+ "margin": {
393
+ "b": 60,
394
+ "l": 0,
395
+ "r": 0,
396
+ "t": 60
397
+ },
398
+ "template": {
399
+ "data": {
400
+ "bar": [
401
+ {
402
+ "error_x": {
403
+ "color": "#2a3f5f"
404
+ },
405
+ "error_y": {
406
+ "color": "#2a3f5f"
407
+ },
408
+ "marker": {
409
+ "line": {
410
+ "color": "#E5ECF6",
411
+ "width": 0.5
412
+ },
413
+ "pattern": {
414
+ "fillmode": "overlay",
415
+ "size": 10,
416
+ "solidity": 0.2
417
+ }
418
+ },
419
+ "type": "bar"
420
+ }
421
+ ],
422
+ "barpolar": [
423
+ {
424
+ "marker": {
425
+ "line": {
426
+ "color": "#E5ECF6",
427
+ "width": 0.5
428
+ },
429
+ "pattern": {
430
+ "fillmode": "overlay",
431
+ "size": 10,
432
+ "solidity": 0.2
433
+ }
434
+ },
435
+ "type": "barpolar"
436
+ }
437
+ ],
438
+ "carpet": [
439
+ {
440
+ "aaxis": {
441
+ "endlinecolor": "#2a3f5f",
442
+ "gridcolor": "white",
443
+ "linecolor": "white",
444
+ "minorgridcolor": "white",
445
+ "startlinecolor": "#2a3f5f"
446
+ },
447
+ "baxis": {
448
+ "endlinecolor": "#2a3f5f",
449
+ "gridcolor": "white",
450
+ "linecolor": "white",
451
+ "minorgridcolor": "white",
452
+ "startlinecolor": "#2a3f5f"
453
+ },
454
+ "type": "carpet"
455
+ }
456
+ ],
457
+ "choropleth": [
458
+ {
459
+ "colorbar": {
460
+ "outlinewidth": 0,
461
+ "ticks": ""
462
+ },
463
+ "type": "choropleth"
464
+ }
465
+ ],
466
+ "contour": [
467
+ {
468
+ "colorbar": {
469
+ "outlinewidth": 0,
470
+ "ticks": ""
471
+ },
472
+ "colorscale": [
473
+ [
474
+ 0,
475
+ "#0d0887"
476
+ ],
477
+ [
478
+ 0.1111111111111111,
479
+ "#46039f"
480
+ ],
481
+ [
482
+ 0.2222222222222222,
483
+ "#7201a8"
484
+ ],
485
+ [
486
+ 0.3333333333333333,
487
+ "#9c179e"
488
+ ],
489
+ [
490
+ 0.4444444444444444,
491
+ "#bd3786"
492
+ ],
493
+ [
494
+ 0.5555555555555556,
495
+ "#d8576b"
496
+ ],
497
+ [
498
+ 0.6666666666666666,
499
+ "#ed7953"
500
+ ],
501
+ [
502
+ 0.7777777777777778,
503
+ "#fb9f3a"
504
+ ],
505
+ [
506
+ 0.8888888888888888,
507
+ "#fdca26"
508
+ ],
509
+ [
510
+ 1,
511
+ "#f0f921"
512
+ ]
513
+ ],
514
+ "type": "contour"
515
+ }
516
+ ],
517
+ "contourcarpet": [
518
+ {
519
+ "colorbar": {
520
+ "outlinewidth": 0,
521
+ "ticks": ""
522
+ },
523
+ "type": "contourcarpet"
524
+ }
525
+ ],
526
+ "heatmap": [
527
+ {
528
+ "colorbar": {
529
+ "outlinewidth": 0,
530
+ "ticks": ""
531
+ },
532
+ "colorscale": [
533
+ [
534
+ 0,
535
+ "#0d0887"
536
+ ],
537
+ [
538
+ 0.1111111111111111,
539
+ "#46039f"
540
+ ],
541
+ [
542
+ 0.2222222222222222,
543
+ "#7201a8"
544
+ ],
545
+ [
546
+ 0.3333333333333333,
547
+ "#9c179e"
548
+ ],
549
+ [
550
+ 0.4444444444444444,
551
+ "#bd3786"
552
+ ],
553
+ [
554
+ 0.5555555555555556,
555
+ "#d8576b"
556
+ ],
557
+ [
558
+ 0.6666666666666666,
559
+ "#ed7953"
560
+ ],
561
+ [
562
+ 0.7777777777777778,
563
+ "#fb9f3a"
564
+ ],
565
+ [
566
+ 0.8888888888888888,
567
+ "#fdca26"
568
+ ],
569
+ [
570
+ 1,
571
+ "#f0f921"
572
+ ]
573
+ ],
574
+ "type": "heatmap"
575
+ }
576
+ ],
577
+ "heatmapgl": [
578
+ {
579
+ "colorbar": {
580
+ "outlinewidth": 0,
581
+ "ticks": ""
582
+ },
583
+ "colorscale": [
584
+ [
585
+ 0,
586
+ "#0d0887"
587
+ ],
588
+ [
589
+ 0.1111111111111111,
590
+ "#46039f"
591
+ ],
592
+ [
593
+ 0.2222222222222222,
594
+ "#7201a8"
595
+ ],
596
+ [
597
+ 0.3333333333333333,
598
+ "#9c179e"
599
+ ],
600
+ [
601
+ 0.4444444444444444,
602
+ "#bd3786"
603
+ ],
604
+ [
605
+ 0.5555555555555556,
606
+ "#d8576b"
607
+ ],
608
+ [
609
+ 0.6666666666666666,
610
+ "#ed7953"
611
+ ],
612
+ [
613
+ 0.7777777777777778,
614
+ "#fb9f3a"
615
+ ],
616
+ [
617
+ 0.8888888888888888,
618
+ "#fdca26"
619
+ ],
620
+ [
621
+ 1,
622
+ "#f0f921"
623
+ ]
624
+ ],
625
+ "type": "heatmapgl"
626
+ }
627
+ ],
628
+ "histogram": [
629
+ {
630
+ "marker": {
631
+ "pattern": {
632
+ "fillmode": "overlay",
633
+ "size": 10,
634
+ "solidity": 0.2
635
+ }
636
+ },
637
+ "type": "histogram"
638
+ }
639
+ ],
640
+ "histogram2d": [
641
+ {
642
+ "colorbar": {
643
+ "outlinewidth": 0,
644
+ "ticks": ""
645
+ },
646
+ "colorscale": [
647
+ [
648
+ 0,
649
+ "#0d0887"
650
+ ],
651
+ [
652
+ 0.1111111111111111,
653
+ "#46039f"
654
+ ],
655
+ [
656
+ 0.2222222222222222,
657
+ "#7201a8"
658
+ ],
659
+ [
660
+ 0.3333333333333333,
661
+ "#9c179e"
662
+ ],
663
+ [
664
+ 0.4444444444444444,
665
+ "#bd3786"
666
+ ],
667
+ [
668
+ 0.5555555555555556,
669
+ "#d8576b"
670
+ ],
671
+ [
672
+ 0.6666666666666666,
673
+ "#ed7953"
674
+ ],
675
+ [
676
+ 0.7777777777777778,
677
+ "#fb9f3a"
678
+ ],
679
+ [
680
+ 0.8888888888888888,
681
+ "#fdca26"
682
+ ],
683
+ [
684
+ 1,
685
+ "#f0f921"
686
+ ]
687
+ ],
688
+ "type": "histogram2d"
689
+ }
690
+ ],
691
+ "histogram2dcontour": [
692
+ {
693
+ "colorbar": {
694
+ "outlinewidth": 0,
695
+ "ticks": ""
696
+ },
697
+ "colorscale": [
698
+ [
699
+ 0,
700
+ "#0d0887"
701
+ ],
702
+ [
703
+ 0.1111111111111111,
704
+ "#46039f"
705
+ ],
706
+ [
707
+ 0.2222222222222222,
708
+ "#7201a8"
709
+ ],
710
+ [
711
+ 0.3333333333333333,
712
+ "#9c179e"
713
+ ],
714
+ [
715
+ 0.4444444444444444,
716
+ "#bd3786"
717
+ ],
718
+ [
719
+ 0.5555555555555556,
720
+ "#d8576b"
721
+ ],
722
+ [
723
+ 0.6666666666666666,
724
+ "#ed7953"
725
+ ],
726
+ [
727
+ 0.7777777777777778,
728
+ "#fb9f3a"
729
+ ],
730
+ [
731
+ 0.8888888888888888,
732
+ "#fdca26"
733
+ ],
734
+ [
735
+ 1,
736
+ "#f0f921"
737
+ ]
738
+ ],
739
+ "type": "histogram2dcontour"
740
+ }
741
+ ],
742
+ "mesh3d": [
743
+ {
744
+ "colorbar": {
745
+ "outlinewidth": 0,
746
+ "ticks": ""
747
+ },
748
+ "type": "mesh3d"
749
+ }
750
+ ],
751
+ "parcoords": [
752
+ {
753
+ "line": {
754
+ "colorbar": {
755
+ "outlinewidth": 0,
756
+ "ticks": ""
757
+ }
758
+ },
759
+ "type": "parcoords"
760
+ }
761
+ ],
762
+ "pie": [
763
+ {
764
+ "automargin": true,
765
+ "type": "pie"
766
+ }
767
+ ],
768
+ "scatter": [
769
+ {
770
+ "fillpattern": {
771
+ "fillmode": "overlay",
772
+ "size": 10,
773
+ "solidity": 0.2
774
+ },
775
+ "type": "scatter"
776
+ }
777
+ ],
778
+ "scatter3d": [
779
+ {
780
+ "line": {
781
+ "colorbar": {
782
+ "outlinewidth": 0,
783
+ "ticks": ""
784
+ }
785
+ },
786
+ "marker": {
787
+ "colorbar": {
788
+ "outlinewidth": 0,
789
+ "ticks": ""
790
+ }
791
+ },
792
+ "type": "scatter3d"
793
+ }
794
+ ],
795
+ "scattercarpet": [
796
+ {
797
+ "marker": {
798
+ "colorbar": {
799
+ "outlinewidth": 0,
800
+ "ticks": ""
801
+ }
802
+ },
803
+ "type": "scattercarpet"
804
+ }
805
+ ],
806
+ "scattergeo": [
807
+ {
808
+ "marker": {
809
+ "colorbar": {
810
+ "outlinewidth": 0,
811
+ "ticks": ""
812
+ }
1556
813
  },
1557
- "file_extension": ".py",
1558
- "mimetype": "text/x-python",
1559
- "name": "python",
1560
- "nbconvert_exporter": "python",
1561
- "pygments_lexer": "ipython3",
1562
- "version": "3.9.19"
814
+ "type": "scattergeo"
815
+ }
816
+ ],
817
+ "scattergl": [
818
+ {
819
+ "marker": {
820
+ "colorbar": {
821
+ "outlinewidth": 0,
822
+ "ticks": ""
823
+ }
824
+ },
825
+ "type": "scattergl"
826
+ }
827
+ ],
828
+ "scattermapbox": [
829
+ {
830
+ "marker": {
831
+ "colorbar": {
832
+ "outlinewidth": 0,
833
+ "ticks": ""
834
+ }
835
+ },
836
+ "type": "scattermapbox"
837
+ }
838
+ ],
839
+ "scatterpolar": [
840
+ {
841
+ "marker": {
842
+ "colorbar": {
843
+ "outlinewidth": 0,
844
+ "ticks": ""
845
+ }
846
+ },
847
+ "type": "scatterpolar"
848
+ }
849
+ ],
850
+ "scatterpolargl": [
851
+ {
852
+ "marker": {
853
+ "colorbar": {
854
+ "outlinewidth": 0,
855
+ "ticks": ""
856
+ }
857
+ },
858
+ "type": "scatterpolargl"
859
+ }
860
+ ],
861
+ "scatterternary": [
862
+ {
863
+ "marker": {
864
+ "colorbar": {
865
+ "outlinewidth": 0,
866
+ "ticks": ""
867
+ }
868
+ },
869
+ "type": "scatterternary"
870
+ }
871
+ ],
872
+ "surface": [
873
+ {
874
+ "colorbar": {
875
+ "outlinewidth": 0,
876
+ "ticks": ""
877
+ },
878
+ "colorscale": [
879
+ [
880
+ 0,
881
+ "#0d0887"
882
+ ],
883
+ [
884
+ 0.1111111111111111,
885
+ "#46039f"
886
+ ],
887
+ [
888
+ 0.2222222222222222,
889
+ "#7201a8"
890
+ ],
891
+ [
892
+ 0.3333333333333333,
893
+ "#9c179e"
894
+ ],
895
+ [
896
+ 0.4444444444444444,
897
+ "#bd3786"
898
+ ],
899
+ [
900
+ 0.5555555555555556,
901
+ "#d8576b"
902
+ ],
903
+ [
904
+ 0.6666666666666666,
905
+ "#ed7953"
906
+ ],
907
+ [
908
+ 0.7777777777777778,
909
+ "#fb9f3a"
910
+ ],
911
+ [
912
+ 0.8888888888888888,
913
+ "#fdca26"
914
+ ],
915
+ [
916
+ 1,
917
+ "#f0f921"
918
+ ]
919
+ ],
920
+ "type": "surface"
921
+ }
922
+ ],
923
+ "table": [
924
+ {
925
+ "cells": {
926
+ "fill": {
927
+ "color": "#EBF0F8"
928
+ },
929
+ "line": {
930
+ "color": "white"
931
+ }
932
+ },
933
+ "header": {
934
+ "fill": {
935
+ "color": "#C8D4E3"
936
+ },
937
+ "line": {
938
+ "color": "white"
939
+ }
940
+ },
941
+ "type": "table"
942
+ }
943
+ ]
944
+ },
945
+ "layout": {
946
+ "annotationdefaults": {
947
+ "arrowcolor": "#2a3f5f",
948
+ "arrowhead": 0,
949
+ "arrowwidth": 1
950
+ },
951
+ "autotypenumbers": "strict",
952
+ "coloraxis": {
953
+ "colorbar": {
954
+ "outlinewidth": 0,
955
+ "ticks": ""
956
+ }
957
+ },
958
+ "colorscale": {
959
+ "diverging": [
960
+ [
961
+ 0,
962
+ "#8e0152"
963
+ ],
964
+ [
965
+ 0.1,
966
+ "#c51b7d"
967
+ ],
968
+ [
969
+ 0.2,
970
+ "#de77ae"
971
+ ],
972
+ [
973
+ 0.3,
974
+ "#f1b6da"
975
+ ],
976
+ [
977
+ 0.4,
978
+ "#fde0ef"
979
+ ],
980
+ [
981
+ 0.5,
982
+ "#f7f7f7"
983
+ ],
984
+ [
985
+ 0.6,
986
+ "#e6f5d0"
987
+ ],
988
+ [
989
+ 0.7,
990
+ "#b8e186"
991
+ ],
992
+ [
993
+ 0.8,
994
+ "#7fbc41"
995
+ ],
996
+ [
997
+ 0.9,
998
+ "#4d9221"
999
+ ],
1000
+ [
1001
+ 1,
1002
+ "#276419"
1003
+ ]
1004
+ ],
1005
+ "sequential": [
1006
+ [
1007
+ 0,
1008
+ "#0d0887"
1009
+ ],
1010
+ [
1011
+ 0.1111111111111111,
1012
+ "#46039f"
1013
+ ],
1014
+ [
1015
+ 0.2222222222222222,
1016
+ "#7201a8"
1017
+ ],
1018
+ [
1019
+ 0.3333333333333333,
1020
+ "#9c179e"
1021
+ ],
1022
+ [
1023
+ 0.4444444444444444,
1024
+ "#bd3786"
1025
+ ],
1026
+ [
1027
+ 0.5555555555555556,
1028
+ "#d8576b"
1029
+ ],
1030
+ [
1031
+ 0.6666666666666666,
1032
+ "#ed7953"
1033
+ ],
1034
+ [
1035
+ 0.7777777777777778,
1036
+ "#fb9f3a"
1037
+ ],
1038
+ [
1039
+ 0.8888888888888888,
1040
+ "#fdca26"
1041
+ ],
1042
+ [
1043
+ 1,
1044
+ "#f0f921"
1045
+ ]
1046
+ ],
1047
+ "sequentialminus": [
1048
+ [
1049
+ 0,
1050
+ "#0d0887"
1051
+ ],
1052
+ [
1053
+ 0.1111111111111111,
1054
+ "#46039f"
1055
+ ],
1056
+ [
1057
+ 0.2222222222222222,
1058
+ "#7201a8"
1059
+ ],
1060
+ [
1061
+ 0.3333333333333333,
1062
+ "#9c179e"
1063
+ ],
1064
+ [
1065
+ 0.4444444444444444,
1066
+ "#bd3786"
1067
+ ],
1068
+ [
1069
+ 0.5555555555555556,
1070
+ "#d8576b"
1071
+ ],
1072
+ [
1073
+ 0.6666666666666666,
1074
+ "#ed7953"
1075
+ ],
1076
+ [
1077
+ 0.7777777777777778,
1078
+ "#fb9f3a"
1079
+ ],
1080
+ [
1081
+ 0.8888888888888888,
1082
+ "#fdca26"
1083
+ ],
1084
+ [
1085
+ 1,
1086
+ "#f0f921"
1087
+ ]
1088
+ ]
1089
+ },
1090
+ "colorway": [
1091
+ "#636efa",
1092
+ "#EF553B",
1093
+ "#00cc96",
1094
+ "#ab63fa",
1095
+ "#FFA15A",
1096
+ "#19d3f3",
1097
+ "#FF6692",
1098
+ "#B6E880",
1099
+ "#FF97FF",
1100
+ "#FECB52"
1101
+ ],
1102
+ "font": {
1103
+ "color": "#2a3f5f"
1104
+ },
1105
+ "geo": {
1106
+ "bgcolor": "white",
1107
+ "lakecolor": "white",
1108
+ "landcolor": "#E5ECF6",
1109
+ "showlakes": true,
1110
+ "showland": true,
1111
+ "subunitcolor": "white"
1112
+ },
1113
+ "hoverlabel": {
1114
+ "align": "left"
1115
+ },
1116
+ "hovermode": "closest",
1117
+ "mapbox": {
1118
+ "style": "light"
1119
+ },
1120
+ "paper_bgcolor": "white",
1121
+ "plot_bgcolor": "#E5ECF6",
1122
+ "polar": {
1123
+ "angularaxis": {
1124
+ "gridcolor": "white",
1125
+ "linecolor": "white",
1126
+ "ticks": ""
1127
+ },
1128
+ "bgcolor": "#E5ECF6",
1129
+ "radialaxis": {
1130
+ "gridcolor": "white",
1131
+ "linecolor": "white",
1132
+ "ticks": ""
1133
+ }
1134
+ },
1135
+ "scene": {
1136
+ "xaxis": {
1137
+ "backgroundcolor": "#E5ECF6",
1138
+ "gridcolor": "white",
1139
+ "gridwidth": 2,
1140
+ "linecolor": "white",
1141
+ "showbackground": true,
1142
+ "ticks": "",
1143
+ "zerolinecolor": "white"
1144
+ },
1145
+ "yaxis": {
1146
+ "backgroundcolor": "#E5ECF6",
1147
+ "gridcolor": "white",
1148
+ "gridwidth": 2,
1149
+ "linecolor": "white",
1150
+ "showbackground": true,
1151
+ "ticks": "",
1152
+ "zerolinecolor": "white"
1153
+ },
1154
+ "zaxis": {
1155
+ "backgroundcolor": "#E5ECF6",
1156
+ "gridcolor": "white",
1157
+ "gridwidth": 2,
1158
+ "linecolor": "white",
1159
+ "showbackground": true,
1160
+ "ticks": "",
1161
+ "zerolinecolor": "white"
1162
+ }
1163
+ },
1164
+ "shapedefaults": {
1165
+ "line": {
1166
+ "color": "#2a3f5f"
1167
+ }
1168
+ },
1169
+ "ternary": {
1170
+ "aaxis": {
1171
+ "gridcolor": "white",
1172
+ "linecolor": "white",
1173
+ "ticks": ""
1174
+ },
1175
+ "baxis": {
1176
+ "gridcolor": "white",
1177
+ "linecolor": "white",
1178
+ "ticks": ""
1179
+ },
1180
+ "bgcolor": "#E5ECF6",
1181
+ "caxis": {
1182
+ "gridcolor": "white",
1183
+ "linecolor": "white",
1184
+ "ticks": ""
1185
+ }
1186
+ },
1187
+ "title": {
1188
+ "x": 0.05
1189
+ },
1190
+ "xaxis": {
1191
+ "automargin": true,
1192
+ "gridcolor": "white",
1193
+ "linecolor": "white",
1194
+ "ticks": "",
1195
+ "title": {
1196
+ "standoff": 15
1197
+ },
1198
+ "zerolinecolor": "white",
1199
+ "zerolinewidth": 2
1200
+ },
1201
+ "yaxis": {
1202
+ "automargin": true,
1203
+ "gridcolor": "white",
1204
+ "linecolor": "white",
1205
+ "ticks": "",
1206
+ "title": {
1207
+ "standoff": 15
1208
+ },
1209
+ "zerolinecolor": "white",
1210
+ "zerolinewidth": 2
1211
+ }
1212
+ }
1213
+ },
1214
+ "xaxis": {
1215
+ "tickmode": "array",
1216
+ "ticktext": [
1217
+ "Patch",
1218
+ "Minor",
1219
+ "Major",
1220
+ "No fixed version"
1221
+ ],
1222
+ "tickvals": [
1223
+ 0,
1224
+ 1,
1225
+ 2,
1226
+ 3
1227
+ ],
1228
+ "title": {
1229
+ "text": "Type of version required to fix vulnerability"
1230
+ }
1231
+ },
1232
+ "yaxis": {
1233
+ "title": {
1234
+ "text": "Vulnerability count"
1235
+ }
1563
1236
  }
1564
- },
1565
- "nbformat": 4,
1566
- "nbformat_minor": 4
1237
+ }
1238
+ }
1239
+ },
1240
+ "metadata": {},
1241
+ "output_type": "display_data"
1242
+ }
1243
+ ],
1244
+ "source": [
1245
+ "import pandas as pd\n",
1246
+ "import warnings\n",
1247
+ "import plotly.graph_objects as go\n",
1248
+ "import code_data_science.data_table as dt\n",
1249
+ "\n",
1250
+ "warnings.simplefilter(\"ignore\")\n",
1251
+ "\n",
1252
+ "df = dt.read_csv(\"../samples/dependency_vulnerabilities.csv\")\n",
1253
+ "\n",
1254
+ "df[\"repositoryWithBranch\"] = df[\"repositoryPath\"] + \"/\" + df[\"repositoryBranch\"]\n",
1255
+ "\n",
1256
+ "# Filter the data frame to only include rows where repositoryWithBranch contain\n",
1257
+ "# a term in the repository_filter (case insensitive)\n",
1258
+ "if len(repository_filter) > 0:\n",
1259
+ " df = df[\n",
1260
+ " df[\"repositoryWithBranch\"].str.contains(\"|\".join(repository_filter), case=False)\n",
1261
+ " ]\n",
1262
+ "\n",
1263
+ "\n",
1264
+ "def create_bar_plot(df_direct, df_transitive):\n",
1265
+ " if df_direct is None or df_transitive is None:\n",
1266
+ " # Create empty dataframes with the correct structure\n",
1267
+ " fix_types = [\"Patch\", \"Minor\", \"Major\", \"No fixed version\"]\n",
1268
+ " df_direct = pd.DataFrame(\n",
1269
+ " {\n",
1270
+ " \"Type\": fix_types,\n",
1271
+ " \"Low\": [0] * 4,\n",
1272
+ " \"Moderate\": [0] * 4,\n",
1273
+ " \"High\": [0] * 4,\n",
1274
+ " \"Critical\": [0] * 4,\n",
1275
+ " }\n",
1276
+ " )\n",
1277
+ " df_transitive = pd.DataFrame(\n",
1278
+ " {\n",
1279
+ " \"Type\": fix_types,\n",
1280
+ " \"Low\": [0] * 4,\n",
1281
+ " \"Moderate\": [0] * 4,\n",
1282
+ " \"High\": [0] * 4,\n",
1283
+ " \"Critical\": [0] * 4,\n",
1284
+ " }\n",
1285
+ " )\n",
1286
+ "\n",
1287
+ " fig = go.Figure()\n",
1288
+ "\n",
1289
+ " # Define colors for severity levels\n",
1290
+ " colors = {\n",
1291
+ " \"Critical\": \"#FF5B5B\",\n",
1292
+ " \"High\": \"#FABA49\",\n",
1293
+ " \"Moderate\": \"#FEE968\",\n",
1294
+ " \"Low\": \"#52BBA0\",\n",
1295
+ " }\n",
1296
+ "\n",
1297
+ " # Calculate totals for percentage calculations\n",
1298
+ " df_direct[\"Total\"] = df_direct[[\"Critical\", \"High\", \"Moderate\", \"Low\"]].sum(axis=1)\n",
1299
+ " df_transitive[\"Total\"] = df_transitive[[\"Critical\", \"High\", \"Moderate\", \"Low\"]].sum(\n",
1300
+ " axis=1\n",
1301
+ " )\n",
1302
+ " grand_total = df_direct[\"Total\"].sum() + df_transitive[\"Total\"].sum()\n",
1303
+ "\n",
1304
+ " # Create custom x-axis positions for grouping\n",
1305
+ " fix_types = df_direct[\"Type\"].tolist()\n",
1306
+ " n_groups = len(fix_types)\n",
1307
+ "\n",
1308
+ " # Create x positions: each group gets positions like [0, 0.4], [1, 1.4], [2, 2.4], etc.\n",
1309
+ " x_direct = [i - 0.2 for i in range(n_groups)]\n",
1310
+ " x_transitive = [i + 0.2 for i in range(n_groups)]\n",
1311
+ "\n",
1312
+ " # Custom tick labels and positions for the main groups\n",
1313
+ " tick_positions = list(range(n_groups))\n",
1314
+ " tick_labels = fix_types\n",
1315
+ "\n",
1316
+ " # Add traces for direct dependencies\n",
1317
+ " for i, severity in enumerate([\"Low\", \"Moderate\", \"High\", \"Critical\"]):\n",
1318
+ " # Calculate percentages for hover\n",
1319
+ " percentages_direct = []\n",
1320
+ " for idx in range(len(df_direct)):\n",
1321
+ " count = df_direct.iloc[idx][severity]\n",
1322
+ " total_in_category = (\n",
1323
+ " df_direct.iloc[idx][\"Total\"] + df_transitive.iloc[idx][\"Total\"]\n",
1324
+ " )\n",
1325
+ " pct_of_category = (\n",
1326
+ " (count / total_in_category * 100) if total_in_category > 0 else 0\n",
1327
+ " )\n",
1328
+ " pct_of_all = (count / grand_total * 100) if grand_total > 0 else 0\n",
1329
+ " percentages_direct.append(\n",
1330
+ " {\n",
1331
+ " \"category_pct\": round(pct_of_category, 1),\n",
1332
+ " \"total_pct\": round(pct_of_all, 1),\n",
1333
+ " }\n",
1334
+ " )\n",
1335
+ "\n",
1336
+ " fig.add_trace(\n",
1337
+ " go.Bar(\n",
1338
+ " name=severity,\n",
1339
+ " x=x_direct,\n",
1340
+ " y=df_direct[severity],\n",
1341
+ " marker_color=colors[severity],\n",
1342
+ " legendgroup=severity,\n",
1343
+ " showlegend=True,\n",
1344
+ " width=0.35, # Make bars wider\n",
1345
+ " customdata=percentages_direct,\n",
1346
+ " hovertemplate=(\n",
1347
+ " \"<b>%{x}</b><br>\"\n",
1348
+ " + f\"{severity} (Direct): %{{y}}<br>\"\n",
1349
+ " + \"Percent of %{x}: %{customdata.category_pct}%<br>\"\n",
1350
+ " + \"Percent of all: %{customdata.total_pct}%\"\n",
1351
+ " + \"<extra></extra>\"\n",
1352
+ " ),\n",
1353
+ " )\n",
1354
+ " )\n",
1355
+ "\n",
1356
+ " # Add traces for transitive dependencies\n",
1357
+ " for i, severity in enumerate([\"Low\", \"Moderate\", \"High\", \"Critical\"]):\n",
1358
+ " # Calculate percentages for hover\n",
1359
+ " percentages_transitive = []\n",
1360
+ " for idx in range(len(df_transitive)):\n",
1361
+ " count = df_transitive.iloc[idx][severity]\n",
1362
+ " total_in_category = (\n",
1363
+ " df_direct.iloc[idx][\"Total\"] + df_transitive.iloc[idx][\"Total\"]\n",
1364
+ " )\n",
1365
+ " pct_of_category = (\n",
1366
+ " (count / total_in_category * 100) if total_in_category > 0 else 0\n",
1367
+ " )\n",
1368
+ " pct_of_all = (count / grand_total * 100) if grand_total > 0 else 0\n",
1369
+ " percentages_transitive.append(\n",
1370
+ " {\n",
1371
+ " \"category_pct\": round(pct_of_category, 1),\n",
1372
+ " \"total_pct\": round(pct_of_all, 1),\n",
1373
+ " }\n",
1374
+ " )\n",
1375
+ "\n",
1376
+ " fig.add_trace(\n",
1377
+ " go.Bar(\n",
1378
+ " name=f\"{severity} \", # Add space to make it different from direct\n",
1379
+ " x=x_transitive,\n",
1380
+ " y=df_transitive[severity],\n",
1381
+ " marker_color=colors[severity],\n",
1382
+ " marker_pattern_shape=\"/\",\n",
1383
+ " legendgroup=severity,\n",
1384
+ " showlegend=False, # Hide from legend since we'll use annotations\n",
1385
+ " width=0.35, # Make bars wider\n",
1386
+ " customdata=percentages_transitive,\n",
1387
+ " hovertemplate=(\n",
1388
+ " \"<b>%{x}</b><br>\"\n",
1389
+ " + f\"{severity} (Transitive): %{{y}}<br>\"\n",
1390
+ " + \"Percent of %{x}: %{customdata.category_pct}%<br>\"\n",
1391
+ " + \"Percent of all: %{customdata.total_pct}%\"\n",
1392
+ " + \"<extra></extra>\"\n",
1393
+ " ),\n",
1394
+ " )\n",
1395
+ " )\n",
1396
+ "\n",
1397
+ " # Update layout with improved legend\n",
1398
+ " fig.update_layout(\n",
1399
+ " xaxis={\n",
1400
+ " \"title\": \"Type of version required to fix vulnerability\",\n",
1401
+ " \"tickmode\": \"array\",\n",
1402
+ " \"tickvals\": tick_positions,\n",
1403
+ " \"ticktext\": tick_labels,\n",
1404
+ " },\n",
1405
+ " yaxis={\"title\": \"Vulnerability count\"},\n",
1406
+ " barmode=\"stack\",\n",
1407
+ " bargap=0.6, # Increase gap between groups\n",
1408
+ " bargroupgap=0.1, # Small gap within groups\n",
1409
+ " margin=dict(l=0, r=0, t=60, b=60),\n",
1410
+ " legend=dict(\n",
1411
+ " orientation=\"v\",\n",
1412
+ " yanchor=\"top\",\n",
1413
+ " y=0.95,\n",
1414
+ " xanchor=\"left\",\n",
1415
+ " x=1.02,\n",
1416
+ " title=dict(\n",
1417
+ " text=\"Severity Level<br><sub>Solid: Direct | Striped: Transitive</sub>\",\n",
1418
+ " font=dict(size=12),\n",
1419
+ " ),\n",
1420
+ " traceorder=\"reversed\", # Reverse legend order to show Critical first\n",
1421
+ " ),\n",
1422
+ " annotations=[\n",
1423
+ " dict(\n",
1424
+ " text=\"<b>Dependency Vulnerabilities by Fix Type</b>\",\n",
1425
+ " xref=\"paper\",\n",
1426
+ " yref=\"paper\",\n",
1427
+ " x=0.5,\n",
1428
+ " y=1.05,\n",
1429
+ " showarrow=False,\n",
1430
+ " font=dict(size=14),\n",
1431
+ " )\n",
1432
+ " ],\n",
1433
+ " )\n",
1434
+ "\n",
1435
+ " return fig\n",
1436
+ "\n",
1437
+ "\n",
1438
+ "# Exit early if there are no stack traces and render a plot with a message\n",
1439
+ "if len(df) == 0:\n",
1440
+ " fig = create_bar_plot(None, None)\n",
1441
+ " fig.update_yaxes(range=[0, 10])\n",
1442
+ " fig.show(render=\"plotly_mimetype\")\n",
1443
+ "else:\n",
1444
+ "\n",
1445
+ " def get_semver_fix(version, fixed_version):\n",
1446
+ " \"\"\"\n",
1447
+ " looks at current version and fixed version and determines if the fix is a major, minor, patch version, or no fix\n",
1448
+ " \"\"\"\n",
1449
+ " version_components = version.split(\".\")\n",
1450
+ " fixed_components = fixed_version.split(\".\")\n",
1451
+ "\n",
1452
+ " # if fixed version is empty, return \"No fixed version\"\n",
1453
+ " if fixed_version == \"\":\n",
1454
+ " return \"No fixed version\"\n",
1455
+ "\n",
1456
+ " if len(version_components) < 3:\n",
1457
+ " # fill in the missing version components with 0\n",
1458
+ " for i in range(3 - len(version_components)):\n",
1459
+ " version_components.append(\"0\")\n",
1460
+ " if len(fixed_components) < 3:\n",
1461
+ " # fill in the missing version components with 0\n",
1462
+ " for i in range(3 - len(fixed_components)):\n",
1463
+ " fixed_components.append(\"0\")\n",
1464
+ "\n",
1465
+ " elif version_components[0] != fixed_components[0]:\n",
1466
+ " return \"Major\"\n",
1467
+ " elif version_components[1] != fixed_components[1]:\n",
1468
+ " return \"Minor\"\n",
1469
+ " elif version_components[2] != fixed_components[2]:\n",
1470
+ " return \"Patch\"\n",
1471
+ " else:\n",
1472
+ " return \"Unknown\"\n",
1473
+ "\n",
1474
+ " # drop unnecessary columns except depth which we need\n",
1475
+ " df = df.drop(\n",
1476
+ " columns=[\n",
1477
+ " \"repositoryOrigin\",\n",
1478
+ " \"repositoryPath\",\n",
1479
+ " \"repositoryBranch\",\n",
1480
+ " \"repositoryWithBranch\",\n",
1481
+ " \"cve\",\n",
1482
+ " \"groupId\",\n",
1483
+ " \"artifactId\",\n",
1484
+ " \"summary\",\n",
1485
+ " ]\n",
1486
+ " )\n",
1487
+ "\n",
1488
+ " # fill NaN values with empty string\n",
1489
+ " df[\"fixedVersion\"] = df[\"fixedVersion\"].fillna(\"\")\n",
1490
+ " df[\"version\"] = df[\"version\"].fillna(\"\")\n",
1491
+ " # make sure version and fixedVersion is a string\n",
1492
+ " df[\"fixedVersion\"] = df[\"fixedVersion\"].astype(str)\n",
1493
+ " df[\"version\"] = df[\"version\"].astype(str)\n",
1494
+ "\n",
1495
+ " # add column 'semverFix' to dataframe\n",
1496
+ " df[\"semverFix\"] = df.apply(\n",
1497
+ " lambda x: get_semver_fix(x[\"version\"], x[\"fixedVersion\"]), axis=1\n",
1498
+ " )\n",
1499
+ "\n",
1500
+ " # Split into direct and transitive\n",
1501
+ " df_direct = df[df[\"depth\"] == 0]\n",
1502
+ " df_transitive = df[df[\"depth\"] != 0]\n",
1503
+ "\n",
1504
+ " # Define the order for fix types\n",
1505
+ " fix_order = [\"Patch\", \"Minor\", \"Major\", \"No fixed version\"]\n",
1506
+ "\n",
1507
+ " # Create aggregated data for direct dependencies\n",
1508
+ " direct_data = []\n",
1509
+ " for fix_type in fix_order:\n",
1510
+ " fix_df = df_direct[df_direct[\"semverFix\"] == fix_type]\n",
1511
+ " severity_counts = fix_df[\"severity\"].value_counts()\n",
1512
+ " direct_data.append(\n",
1513
+ " {\n",
1514
+ " \"Type\": fix_type,\n",
1515
+ " \"Critical\": severity_counts.get(\"CRITICAL\", 0),\n",
1516
+ " \"High\": severity_counts.get(\"HIGH\", 0),\n",
1517
+ " \"Moderate\": severity_counts.get(\"MODERATE\", 0),\n",
1518
+ " \"Low\": severity_counts.get(\"LOW\", 0),\n",
1519
+ " }\n",
1520
+ " )\n",
1521
+ " df_direct_plot = pd.DataFrame(direct_data)\n",
1522
+ "\n",
1523
+ " # Create aggregated data for transitive dependencies\n",
1524
+ " transitive_data = []\n",
1525
+ " for fix_type in fix_order:\n",
1526
+ " fix_df = df_transitive[df_transitive[\"semverFix\"] == fix_type]\n",
1527
+ " severity_counts = fix_df[\"severity\"].value_counts()\n",
1528
+ " transitive_data.append(\n",
1529
+ " {\n",
1530
+ " \"Type\": fix_type,\n",
1531
+ " \"Critical\": severity_counts.get(\"CRITICAL\", 0),\n",
1532
+ " \"High\": severity_counts.get(\"HIGH\", 0),\n",
1533
+ " \"Moderate\": severity_counts.get(\"MODERATE\", 0),\n",
1534
+ " \"Low\": severity_counts.get(\"LOW\", 0),\n",
1535
+ " }\n",
1536
+ " )\n",
1537
+ " df_transitive_plot = pd.DataFrame(transitive_data)\n",
1538
+ "\n",
1539
+ " fig = create_bar_plot(df_direct_plot, df_transitive_plot)\n",
1540
+ "\n",
1541
+ " # Show the figure\n",
1542
+ " fig.show(render=\"plotly_mimetype\")"
1543
+ ]
1544
+ }
1545
+ ],
1546
+ "metadata": {
1547
+ "kernelspec": {
1548
+ "display_name": ".venv",
1549
+ "language": "python",
1550
+ "name": "python3"
1551
+ },
1552
+ "language_info": {
1553
+ "codemirror_mode": {
1554
+ "name": "ipython",
1555
+ "version": 3
1556
+ },
1557
+ "file_extension": ".py",
1558
+ "mimetype": "text/x-python",
1559
+ "name": "python",
1560
+ "nbconvert_exporter": "python",
1561
+ "pygments_lexer": "ipython3",
1562
+ "version": "3.9.19"
1563
+ }
1564
+ },
1565
+ "nbformat": 4,
1566
+ "nbformat_minor": 4
1567
1567
  }