stored_card.GetAccess() eventually leads to /obj/item/card/id/GetAccess() being called. This proc returns the actual access list associated with the ID card rather than a .Copy() of it.
As a result, the line total_access = stored_card.GetAccess() is storing a reference to the stored_card's actual access list.
total_access |= card_slot2.stored_card.GetAccess() is then mutating the first ID card's access list via the reference.
The result? When /obj/item/computer_hardware/card_slot/GetAccess() is called with 2 ID cards in a modular computer, the second ID card gives all of its accesses to the first ID card thanks to the |= operation.
There are a number of ways around this. Some pieces of code do var/list/thing = list() and then |= every GetAccess() since it's guaranteed to return a list. This creates new lists instead.
However, I feel GetAccess() for ID cards really shouldn't be returning a ref to the list. Instead, it now returns a Copy() of the list and code implementing behaviour using GetAccess() doesn't need to worry about list mutation at all.