Skip to content

Commit 9a6d5ba

Browse files
committed
check if job_id is valid
1 parent 66e6c9f commit 9a6d5ba

File tree

2 files changed

+25
-10
lines changed

2 files changed

+25
-10
lines changed

skills/rca-annotator/scripts/jumpbox_io.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,20 @@
66
"""
77

88
import os
9+
import re
10+
import shlex
911
import subprocess
1012
from pathlib import Path
1113

1214

15+
def _validate_job_id(job_id: str) -> bool:
16+
"""Validate job_id is numeric only to prevent command injection."""
17+
if not re.fullmatch(r"\d+", job_id):
18+
print(f" Error: Invalid job_id '{job_id}'. Must be numeric.")
19+
return False
20+
return True
21+
22+
1323
def parse_jumpbox_uri(jumpbox_uri: str) -> tuple[str, str | None]:
1424
"""
1525
Parse JUMPBOX_URI format: "user@host -p port" or "user@host".
@@ -80,9 +90,7 @@ def download_from_jumpbox(job_id: str, jumpbox_uri: str | None = None) -> bool:
8090
Returns:
8191
True on success, False on failure
8292
"""
83-
# Sanitize job_id to prevent path traversal
84-
if "/" in job_id or "." in job_id:
85-
print(" Error: Invalid job_id format. Cannot contain . or /")
93+
if not _validate_job_id(job_id):
8694
return False
8795

8896
# Get JUMPBOX_URI
@@ -124,7 +132,7 @@ def download_from_jumpbox(job_id: str, jumpbox_uri: str | None = None) -> bool:
124132
ssh_cmd = ["ssh"]
125133
if ssh_port:
126134
ssh_cmd.extend(["-p", ssh_port])
127-
ssh_cmd.extend([ssh_target, f"test -d {candidate}"])
135+
ssh_cmd.extend([ssh_target, f"test -d {shlex.quote(candidate)}"])
128136

129137
try:
130138
subprocess.run(
@@ -194,9 +202,7 @@ def upload_to_jumpbox(job_id: str, jumpbox_uri: str | None = None) -> bool:
194202
Returns:
195203
True on success, False on failure
196204
"""
197-
# Sanitize job_id to prevent path traversal
198-
if "/" in job_id or "." in job_id:
199-
print(" Error: Invalid job_id format. Cannot contain . or /")
205+
if not _validate_job_id(job_id):
200206
return False
201207

202208
local_file = Path(".analysis") / job_id / "annotation_draft.json"

skills/root-cause-analysis/scripts/jumpbox_io.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,20 @@
77

88
import json
99
import os
10+
import re
11+
import shlex
1012
import subprocess
1113
from pathlib import Path
1214

1315

16+
def _validate_job_id(job_id: str) -> bool:
17+
"""Validate job_id is numeric only to prevent command injection."""
18+
if not re.fullmatch(r"\d+", job_id):
19+
print(f" Error: Invalid job_id '{job_id}'. Must be numeric.")
20+
return False
21+
return True
22+
23+
1424
def parse_jumpbox_uri(jumpbox_uri: str) -> tuple[str, str | None]:
1525
"""
1626
Parse JUMPBOX_URI format: "user@host -p port" or "user@host".
@@ -63,8 +73,7 @@ def upload_to_jumpbox(
6373
Returns:
6474
True on success, False on failure
6575
"""
66-
if "/" in job_id or "." in job_id:
67-
print(" Error: Invalid job_id format. Cannot contain . or /")
76+
if not _validate_job_id(job_id):
6877
return False
6978

7079
if not analysis_dir.exists():
@@ -101,7 +110,7 @@ def upload_to_jumpbox(
101110
ssh_cmd = ["ssh"]
102111
if ssh_port:
103112
ssh_cmd.extend(["-p", ssh_port])
104-
ssh_cmd.extend([ssh_target, f"mkdir -p {remote_dir}"])
113+
ssh_cmd.extend([ssh_target, f"mkdir -p {shlex.quote(remote_dir)}"])
105114

106115
try:
107116
subprocess.run(ssh_cmd, check=True, capture_output=True, timeout=30)

0 commit comments

Comments
 (0)