fix: scope trunk nic's associatednetworks to the requested network in listNics
diff --git a/api/src/main/java/org/apache/cloudstack/api/ResponseGenerator.java b/api/src/main/java/org/apache/cloudstack/api/ResponseGenerator.java
index 6e880c8..9f9f1a2 100644
--- a/api/src/main/java/org/apache/cloudstack/api/ResponseGenerator.java
+++ b/api/src/main/java/org/apache/cloudstack/api/ResponseGenerator.java
@@ -529,6 +529,8 @@
 
     public NicResponse createNicResponse(Nic result);
 
+    public NicResponse createNicResponse(Nic result, Long networkId);
+
     ApplicationLoadBalancerResponse createLoadBalancerContainerReponse(ApplicationLoadBalancerRule lb,
             Map<Ip, UserVm> lbInstances);
 
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ListNicsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ListNicsCmd.java
index 7d2b27e..3ea93e0 100644
--- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ListNicsCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ListNicsCmd.java
@@ -143,7 +143,7 @@
                 if (results != null) {
                     resList = new ArrayList<NicResponse>(results.size());
                     for (Nic r : results) {
-                        NicResponse resp = _responseGenerator.createNicResponse(r);
+                        NicResponse resp = _responseGenerator.createNicResponse(r, this.getNetworkId());
                         resp.setObjectName("nic");
                         resList.add(resp);
                     }
diff --git a/server/src/main/java/com/cloud/api/ApiDBUtils.java b/server/src/main/java/com/cloud/api/ApiDBUtils.java
index bd7e6b8..60c827d 100644
--- a/server/src/main/java/com/cloud/api/ApiDBUtils.java
+++ b/server/src/main/java/com/cloud/api/ApiDBUtils.java
@@ -2262,9 +2262,21 @@
      * identical shape, so it's built once here rather than duplicated per builder.
      */
     public static List<NicNetworkMapResponse> findAssociatedNetworkResponses(long nicId) {
+        return findAssociatedNetworkResponses(nicId, null);
+    }
+
+    /**
+     * Same as {@link #findAssociatedNetworkResponses(long)}, narrowed to the given network when one is passed -
+     * for callers like {@code listNics?networkid=X} that asked about one specific network and should not get
+     * back every other network this nic happens to trunk too.
+     */
+    public static List<NicNetworkMapResponse> findAssociatedNetworkResponses(long nicId, Long networkId) {
         List<NicNetworkMapVO> associations = s_nicNetworkMapDao.listByNicId(nicId);
         List<NicNetworkMapResponse> associatedNetworkResponses = new ArrayList<>();
         for (NicNetworkMapVO association : associations) {
+            if (networkId != null && association.getNetworkId() != networkId) {
+                continue;
+            }
             NetworkVO associatedNetwork = findNetworkById(association.getNetworkId());
             if (associatedNetwork == null) {
                 continue;
diff --git a/server/src/main/java/com/cloud/api/ApiResponseHelper.java b/server/src/main/java/com/cloud/api/ApiResponseHelper.java
index 561ce3d..ba86367 100644
--- a/server/src/main/java/com/cloud/api/ApiResponseHelper.java
+++ b/server/src/main/java/com/cloud/api/ApiResponseHelper.java
@@ -4819,6 +4819,16 @@
      */
     @Override
     public NicResponse createNicResponse(Nic result) {
+        return createNicResponse(result, null);
+    }
+
+    /**
+     * Same as {@link #createNicResponse(Nic)}, but when {@code networkId} is given (a {@code listNics?networkid=}
+     * query), the trunk nic's {@code associatednetworks} is narrowed to that one network instead of every
+     * network the nic trunks - callers that asked about one specific network shouldn't get every other one back.
+     */
+    @Override
+    public NicResponse createNicResponse(Nic result, Long networkId) {
         NicResponse response = new NicResponse();
         NetworkVO network = _entityMgr.findById(NetworkVO.class, result.getNetworkId());
         VMInstanceVO vm = _entityMgr.findById(VMInstanceVO.class, result.getInstanceId());
@@ -4894,7 +4904,7 @@
         /*trunked / associatednetworks - multi-VLAN trunk nic, if any*/
         response.setTrunked(result.getMultiNetwork());
         if (result.getMultiNetwork()) {
-            response.setAssociatedNetworks(ApiDBUtils.findAssociatedNetworkResponses(result.getId()));
+            response.setAssociatedNetworks(ApiDBUtils.findAssociatedNetworkResponses(result.getId(), networkId));
         }
         /*18: extra dhcp options */
         List<NicExtraDhcpOptionResponse> nicExtraDhcpOptionResponses = nicExtraDhcpOptionVOs
diff --git a/ui/src/utils/multiNetworkNic.js b/ui/src/utils/multiNetworkNic.js
index 7997ac3..6f17a08 100644
--- a/ui/src/utils/multiNetworkNic.js
+++ b/ui/src/utils/multiNetworkNic.js
@@ -52,15 +52,26 @@
 // Each option carries the networkid a rule-creation call (enableStaticNat/createPortForwardingRule/
 // assignToLoadBalancerRule) must submit alongside its ip - an associated option's networkid differs from
 // the nic's own, which is the one real behavioral difference from a secondary IP.
-export function buildNicIpOptions (nic) {
+//
+// targetNetworkId, when given (the rule's own network - e.g. the public IP's network), excludes the
+// primary/secondary options when the nic's primary network isn't that one: a trunk nic listed as a
+// candidate only because one of its *associated* networks matches must not also offer its unrelated
+// primary IP, which is never valid for this rule.
+export function buildNicIpOptions (nic, targetNetworkId) {
   const options = []
-  if (nic.ipaddress) {
+  const primaryMatches = !targetNetworkId || nic.networkid === targetNetworkId
+  if (nic.ipaddress && primaryMatches) {
     options.push({ kind: 'primary', ip: nic.ipaddress, networkid: nic.networkid, networkname: nic.networkname, nicid: nic.id })
   }
-  for (const secondary of (nic.secondaryip || [])) {
-    options.push({ kind: 'secondary', ip: secondary.ipaddress, networkid: nic.networkid, networkname: nic.networkname, nicid: nic.id })
+  if (primaryMatches) {
+    for (const secondary of (nic.secondaryip || [])) {
+      options.push({ kind: 'secondary', ip: secondary.ipaddress, networkid: nic.networkid, networkname: nic.networkname, nicid: nic.id })
+    }
   }
   for (const association of (nic.associatednetworks || [])) {
+    if (targetNetworkId && association.networkid !== targetNetworkId) {
+      continue
+    }
     options.push({ kind: 'associated', ip: association.ipaddress, networkid: association.networkid, networkname: association.networkname, nicid: nic.id })
   }
   return options
diff --git a/ui/src/views/network/EnableStaticNat.vue b/ui/src/views/network/EnableStaticNat.vue
index bc955cf..2e94946 100644
--- a/ui/src/views/network/EnableStaticNat.vue
+++ b/ui/src/views/network/EnableStaticNat.vue
@@ -230,12 +230,13 @@
       this.selectedVm = e.target.value
       this.nicIpOptions = []
       this.loading = true
+      const networkId = this.resource.associatednetworkid || this.selectedVpcTier
       getAPI('listNics', {
         virtualmachineid: this.selectedVm,
-        networkid: this.resource.associatednetworkid || this.selectedVpcTier
+        networkid: networkId
       }).then(response => {
         const nics = response.listnicsresponse.nic || []
-        this.nicIpOptions = nics.flatMap(nic => buildNicIpOptions(nic))
+        this.nicIpOptions = nics.flatMap(nic => buildNicIpOptions(nic, networkId))
         this.selectedNic = this.nicIpOptions[0]
       }).catch(error => {
         this.$notifyError(error)
diff --git a/ui/src/views/network/InternalLBAssignVmForm.vue b/ui/src/views/network/InternalLBAssignVmForm.vue
index 73f61f3..2dd3308 100644
--- a/ui/src/views/network/InternalLBAssignVmForm.vue
+++ b/ui/src/views/network/InternalLBAssignVmForm.vue
@@ -188,13 +188,14 @@
       }
       this.iLb.virtualmachineid[index] = e.target.value
       this.addVmModalNicLoading = true
+      const networkId = this.resource.networkid
       getAPI('listNics', {
         virtualmachineid: e.target.value,
-        networkid: this.resource.networkid
+        networkid: networkId
       }).then(response => {
         if (!response.listnicsresponse.nic[0]) return
         const nicsReturned = response.listnicsresponse.nic || []
-        this.nics[index] = nicsReturned.flatMap(nic => buildNicIpOptions(nic))
+        this.nics[index] = nicsReturned.flatMap(nic => buildNicIpOptions(nic, networkId))
         this.iLb.vmguestip[index] = this.nics[index][0]?.ip
         this.addVmModalNicLoading = false
       }).catch(error => {
diff --git a/ui/src/views/network/LoadBalancing.vue b/ui/src/views/network/LoadBalancing.vue
index 58fd14e..fc93e5a 100644
--- a/ui/src/views/network/LoadBalancing.vue
+++ b/ui/src/views/network/LoadBalancing.vue
@@ -1854,13 +1854,14 @@
       this.newRule.virtualmachineid[index] = e.target.value
       this.addVmModalNicLoading = true
 
+      const networkId = ('vpcid' in this.resource && (!('associatednetworkid' in this.resource) || this.vpcConserveMode)) ? this.selectedTier : this.resource.associatednetworkid
       getAPI('listNics', {
         virtualmachineid: e.target.value,
-        networkid: ('vpcid' in this.resource && (!('associatednetworkid' in this.resource) || this.vpcConserveMode)) ? this.selectedTier : this.resource.associatednetworkid
+        networkid: networkId
       }).then(response => {
         if (!response || !response.listnicsresponse || !response.listnicsresponse.nic[0]) return
         const nicsReturned = response.listnicsresponse.nic || []
-        this.nics[index] = nicsReturned.flatMap(nic => buildNicIpOptions(nic))
+        this.nics[index] = nicsReturned.flatMap(nic => buildNicIpOptions(nic, networkId))
         this.newRule.vmguestip[index] = [this.nics[index][0]?.ip]
         this.addVmModalNicLoading = false
       }).catch(error => {
diff --git a/ui/src/views/network/PortForwarding.vue b/ui/src/views/network/PortForwarding.vue
index 4026202..4a40304 100644
--- a/ui/src/views/network/PortForwarding.vue
+++ b/ui/src/views/network/PortForwarding.vue
@@ -816,12 +816,13 @@
       this.nicIpOptions = []
       this.addVmModalNicLoading = true
       this.newRule.virtualmachineid = e.target.value
+      const networkId = ('vpcid' in this.resource && (!('associatednetworkid' in this.resource) || this.vpcConserveMode)) ? this.selectedTier : this.resource.associatednetworkid
       getAPI('listNics', {
         virtualmachineid: e.target.value,
-        networkid: ('vpcid' in this.resource && (!('associatednetworkid' in this.resource) || this.vpcConserveMode)) ? this.selectedTier : this.resource.associatednetworkid
+        networkid: networkId
       }).then(response => {
         const nics = response.listnicsresponse.nic || []
-        this.nicIpOptions = nics.flatMap(nic => buildNicIpOptions(nic))
+        this.nicIpOptions = nics.flatMap(nic => buildNicIpOptions(nic, networkId))
         this.newRule.vmguestip = this.nicIpOptions[0]?.ip
         this.addVmModalNicLoading = false
       }).catch(error => {