reckless: reduce uv verbosity and avoid flooding output
What changed, and why it matters
This commit fixes a bug in Core Lightning's 'reckless' plugin installer tool. The bug was that very verbose dependency-resolution output from the 'uv' Python package manager was being dumped all at once as JSON to the reckless-rpc plugin, potentially overloading it. The fix both removes the verbose '-v' flag from uv and adds a rate-limiting helper that prints large JSON output in small chunks with tiny delays. It is a reliability/DoS-style bug fix, not a code-execution vulnerability.
Treat as a routine bug fix. Review whether the rate-limiting delay is sufficient for the target RPC buffer size, and consider whether the root cause is the buffer size or the lack of backpressure in reckless-rpc. No urgent security patch cycle is indicated.
Security signals we found
Denial-of-service/reliability concern: large JSON output could overwhelm plugin input buffer
Output rate-limiting added to mitigate flooding
Verbose dependency-resolution output removed to reduce data volume
Changelog labels the issue as a bug introduced in the same release
Evidence from the diff
The change is in tools/reckless. It adds chunk_string() and ratelimit_output() helpers and uses them when printing the final JSON log object. It also removes the ‘-v’ (verbose) flag from two ‘uv’ invocations: ‘uv -v venv’ becomes ‘uv venv’ and ‘uv -v pip install …’ becomes ‘uv pip install …’. The stated reason is that the verbose dependency-resolution output was being emitted all in one shot and overloading the reckless-rpc plugin input. The rate-limiting reduces the chance of flooding the RPC plugin’s input buffer, and removing verbosity removes the bulk of the data.
Changed components
tools/recklessreckless-rpc plugin input handlingInspect captured patch +17 / −3
diff --git a/tools/reckless b/tools/reckless
index bf03354f..16896417 100755
--- a/tools/reckless
+++ b/tools/reckless
@@ -32,6 +32,19 @@ logging.basicConfig(
LAST_FOUND = None
+def chunk_string(string: str, size: int):
+ for i in range(0, len(string), size):
+ yield string[i: i + size]
+
+
+def ratelimit_output(output: str):
+ sys.stdout.reconfigure(encoding='utf-8')
+ for i in chunk_string(output, 1024):
+ sys.stdout.write(i)
+ sys.stdout.flush()
+ time.sleep(0.01)
+
+
class Logger:
"""Redirect logging output to a json object or stdout as appropriate."""
def __init__(self, capture: bool = False):
@@ -89,7 +102,8 @@ class Logger:
isinstance(log.json_output["result"][0], list):
# unpack sources output
log.json_output["result"] = log.json_output["result"][0]
- print(json.dumps(log.json_output, indent=3))
+ output = json.dumps(log.json_output, indent=3) + '\n'
+ ratelimit_output(output)
log = Logger()
@@ -1027,7 +1041,7 @@ def install_python_uv_legacy(cloned_plugin: InstInfo):
(Path(cloned_plugin.source_loc) / 'requirements.txt').\
symlink_to(source / 'requirements.txt')
- venv = run(['uv', '-v', 'venv'], cwd=str(cloned_plugin.source_loc),
+ venv = run(['uv', 'venv'], cwd=str(cloned_plugin.source_loc),
stdout=PIPE, stderr=PIPE, text=True, check=False)
if venv.returncode != 0:
for line in venv.stderr.splitlines():
@@ -1041,7 +1055,7 @@ def install_python_uv_legacy(cloned_plugin: InstInfo):
# Running this as a shell allows overriding any active virtual environment
# which would make uv skip installing packages already present in the
# current env.
- call = ['. .venv/bin/activate; uv -v pip install -r requirements.txt']
+ call = ['. .venv/bin/activate; uv pip install -r requirements.txt']
uv = run(call, shell=True, cwd=str(cloned_plugin.source_loc),
stdout=PIPE, stderr=PIPE, text=True, check=False)
if uv.returncode != 0:
Why this scored 21/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.