Description
nemoclaw/src/blueprint/private-networks.ts loads nemoclaw-blueprint/private-networks.yaml on first use, builds a node:net BlockList, and memoizes it in the module-level cached value.
The cache is only invalidated through resetCache(), which is exposed for tests. In a long-running plugin process, changes to private-networks.yaml are not picked up until the process restarts.
This is fine for short-lived CLI execution, but the OpenClaw plugin can remain loaded for the lifetime of an agent session. If the private network list changes while the process is running, the existing BlockList remains stale.
Expected behavior
The loader should keep the cache for unchanged files, but refresh it when private-networks.yaml changes. A simple metadata check such as mtimeMs plus file size on each load() call would keep the existing synchronous style while avoiding stale blocklists.
Actual behavior
Once getPrivateNetworks(), getNetworkEntries(), isPrivateIp(), or isPrivateHostname() loads the YAML once, later calls reuse the original cached BlockList even if the YAML file has changed.
Affected file
nemoclaw/src/blueprint/private-networks.ts
Reproduction Steps
- Load the private network blocklist once through
getPrivateNetworks() or isPrivateHostname().
- Modify
nemoclaw-blueprint/private-networks.yaml or mock the file contents in a unit test.
- Call
getPrivateNetworks() or isPrivateHostname() again without calling resetCache().
- Observe that the previous
BlockList is still used.
- Restart the process or call
resetCache().
- Observe that the updated YAML is only picked up after that manual invalidation.
Minimal regression expectation:
const before = getPrivateNetworks();
writeUpdatedPrivateNetworksYaml();
const after = getPrivateNetworks();
expect(after).not.toBe(before);
expect(isPrivateHostname("newly-blocked-address-or-host")).toBe(true);
Environment
- OS: macOS / Linux / Windows + WSL2
- Node.js: >=22.16.0
- Docker: Not required for reproduction
- NemoClaw: current
main
- Affected runtime: long-running OpenClaw plugin process
Debug Output
Not applicable. This is a cache invalidation issue visible from static inspection and a small unit test.
Relevant behavior:
- `private-networks.ts` stores the parsed YAML and `BlockList` in module-level `cached`.
- `load()` returns `cached` immediately after the first load.
- `resetCache()` is test-only and not part of normal plugin refresh behavior.
Logs
No runtime logs are emitted for this path.
A focused regression test should fail before the fix and pass after adding file metadata-based invalidation:
npm test -- private-networks.test.ts
Checklist
Description
nemoclaw/src/blueprint/private-networks.tsloadsnemoclaw-blueprint/private-networks.yamlon first use, builds anode:netBlockList, and memoizes it in the module-levelcachedvalue.The cache is only invalidated through
resetCache(), which is exposed for tests. In a long-running plugin process, changes toprivate-networks.yamlare not picked up until the process restarts.This is fine for short-lived CLI execution, but the OpenClaw plugin can remain loaded for the lifetime of an agent session. If the private network list changes while the process is running, the existing
BlockListremains stale.Expected behavior
The loader should keep the cache for unchanged files, but refresh it when
private-networks.yamlchanges. A simple metadata check such asmtimeMsplus file size on eachload()call would keep the existing synchronous style while avoiding stale blocklists.Actual behavior
Once
getPrivateNetworks(),getNetworkEntries(),isPrivateIp(), orisPrivateHostname()loads the YAML once, later calls reuse the original cachedBlockListeven if the YAML file has changed.Affected file
nemoclaw/src/blueprint/private-networks.tsReproduction Steps
getPrivateNetworks()orisPrivateHostname().nemoclaw-blueprint/private-networks.yamlor mock the file contents in a unit test.getPrivateNetworks()orisPrivateHostname()again without callingresetCache().BlockListis still used.resetCache().Minimal regression expectation:
Environment
mainDebug Output
Logs
Checklist