Skip to content

WhiteBoxNetSecGame: Stale action space after dynamic IP change #480

@harpomaxx

Description

@harpomaxx

Bug Description

WhiteBoxNetSecGame._all_actions and _registration_info are computed once during _initialize() (line 28-31 of WhiteBoxNetSecGame.py) and never regenerated when _dynamic_ip_change() is called during reset(). After a reset with dynamic IPs enabled, the entire WhiteBox action list references old/invalid IPs that no longer exist in the game. Agents operating in WhiteBox mode receive a completely stale and incorrect action space.

Additionally, even if a fix attempted to call _generate_all_actions() again after a dynamic IP change, it would crash with a KeyError on line 41:

all_ips = [self._ip_mapping[ip] for ip in self._ip_to_hostname.keys()]

This is because after _dynamic_ip_change():

  • self._ip_to_hostname keys are remapped (new) IPs
  • self._ip_mapping keys are original IPs (never change)
  • Looking up a new IP in _ip_mapping raises KeyError

The same root cause also affects NetSecGame._get_all_local_ips() (line 1041), which crashes when a starting position uses the "all_local" keyword after a dynamic IP change.

Steps to Reproduce

  1. Configure a game scenario with use_dynamic_ips: true in the task config
  2. Start a WhiteBoxNetSecGame server
  3. Connect an agent and complete an episode
  4. Request a reset with randomize_topology: true
  5. Observe that the _all_actions list (sent during registration) now contains IPs that no longer exist in the game
  6. If an agent reconnects (re-registers), it still receives the stale action list
  7. If the starting position uses "all_local", the game crashes with KeyError in _get_all_local_ips() at line 1041 of NetSecGame.py

Expected Behavior

After a reset with dynamic IP changes:

  1. WhiteBoxNetSecGame should regenerate _all_actions and _registration_info with the new IPs so that reconnecting agents receive a valid, up-to-date action space.
  2. _generate_all_actions() should work correctly with remapped IPs (the _ip_mapping lookup on line 41 needs to be fixed or bypassed since _ip_to_hostname already contains the current/mapped IPs).
  3. _get_all_local_ips() in NetSecGame.py should not crash -- it should use the IPs from _networks directly instead of going through _ip_mapping, since _networks is already updated with the new IPs.

Suggested fix for _generate_all_actions() line 41:

# Before (broken after dynamic IP change):
all_ips = [self._ip_mapping[ip] for ip in self._ip_to_hostname.keys()]

# After (use _ip_to_hostname keys directly -- they already contain current IPs):
all_ips = list(self._ip_to_hostname.keys())

Suggested fix for _get_all_local_ips() line 1041:

# Before (broken after dynamic IP change):
local_ips.add(self._ip_mapping[ip])

# After (IPs in _networks are already current):
local_ips.add(ip)

Suggested fix for WhiteBoxNetSecGame.reset():

Override reset() to regenerate _all_actions and _registration_info:

async def reset(self) -> bool:
    result = await super().reset()
    self._all_actions = self._generate_all_actions()
    self._registration_info = {
        "all_actions": json.dumps([v.as_dict for v in self._all_actions]),
    } if self._all_actions is not None else {}
    return result

Version

Current main branch (commit 3943658)

Installation / Deployment Method

Running locally from source

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions