Skip to content

Commit 8861546

Browse files
authored
[Security] Add Bandit (#795)
1 parent 9c1a893 commit 8861546

File tree

6 files changed

+66
-37
lines changed

6 files changed

+66
-37
lines changed

.pre-commit-config.yaml

+13-4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ exclude: ^(tests/data)
22
default_language_version:
33
python: python3.10
44
repos:
5+
##### Style / Misc. #####
56
- repo: https://github.com/pre-commit/pre-commit-hooks
67
rev: v5.0.0
78
hooks:
@@ -14,7 +15,7 @@ repos:
1415
- id: end-of-file-fixer
1516
- id: trailing-whitespace
1617
- repo: https://github.com/crate-ci/typos
17-
rev: v1.29.10
18+
rev: v1.30.0
1819
hooks:
1920
- id: typos
2021
args: [--force-exclude]
@@ -23,16 +24,24 @@ repos:
2324
hooks:
2425
- id: pyupgrade
2526
- repo: https://github.com/astral-sh/ruff-pre-commit
26-
rev: v0.9.6
27+
rev: v0.9.9
2728
hooks:
2829
- id: ruff
2930
args: [--fix]
3031
- id: ruff-format
32+
33+
##### Security #####
3134
- repo: https://github.com/gitleaks/gitleaks
32-
rev: v8.23.3
35+
rev: v8.24.0
3336
hooks:
3437
- id: gitleaks
3538
- repo: https://github.com/woodruffw/zizmor-pre-commit
36-
rev: v1.3.1
39+
rev: v1.4.1
3740
hooks:
3841
- id: zizmor
42+
- repo: https://github.com/PyCQA/bandit
43+
rev: 1.8.3
44+
hooks:
45+
- id: bandit
46+
args: ["-c", "pyproject.toml"]
47+
additional_dependencies: ["bandit[toml]"]

lerobot/common/utils/utils.py

+24-15
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import os
1818
import os.path as osp
1919
import platform
20+
import subprocess
2021
from copy import copy
2122
from datetime import datetime, timezone
2223
from pathlib import Path
@@ -165,23 +166,31 @@ def capture_timestamp_utc():
165166

166167

167168
def say(text, blocking=False):
168-
# Check if mac, linux, or windows.
169-
if platform.system() == "Darwin":
170-
cmd = f'say "{text}"'
171-
if not blocking:
172-
cmd += " &"
173-
elif platform.system() == "Linux":
174-
cmd = f'spd-say "{text}"'
169+
system = platform.system()
170+
171+
if system == "Darwin":
172+
cmd = ["say", text]
173+
174+
elif system == "Linux":
175+
cmd = ["spd-say", text]
175176
if blocking:
176-
cmd += " --wait"
177-
elif platform.system() == "Windows":
178-
# TODO(rcadene): Make blocking option work for Windows
179-
cmd = (
180-
'PowerShell -Command "Add-Type -AssemblyName System.Speech; '
181-
f"(New-Object System.Speech.Synthesis.SpeechSynthesizer).Speak('{text}')\""
182-
)
177+
cmd.append("--wait")
178+
179+
elif system == "Windows":
180+
cmd = [
181+
"PowerShell",
182+
"-Command",
183+
"Add-Type -AssemblyName System.Speech; "
184+
f"(New-Object System.Speech.Synthesis.SpeechSynthesizer).Speak('{text}')",
185+
]
183186

184-
os.system(cmd)
187+
else:
188+
raise RuntimeError("Unsupported operating system for text-to-speech.")
189+
190+
if blocking:
191+
subprocess.run(cmd, check=True)
192+
else:
193+
subprocess.Popen(cmd, creationflags=subprocess.CREATE_NO_WINDOW if system == "Windows" else 0)
185194

186195

187196
def log_say(text, play_sounds, blocking=False):

lerobot/scripts/eval.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ def _compile_episode_data(
454454

455455

456456
@parser.wrap()
457-
def eval(cfg: EvalPipelineConfig):
457+
def eval_main(cfg: EvalPipelineConfig):
458458
logging.info(pformat(asdict(cfg)))
459459

460460
# Check device is available
@@ -499,4 +499,4 @@ def eval(cfg: EvalPipelineConfig):
499499

500500
if __name__ == "__main__":
501501
init_logging()
502-
eval()
502+
eval_main()

lerobot/scripts/visualize_dataset_html.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ def show_episode(dataset_namespace, dataset_name, episode_id, dataset=dataset, e
194194
]
195195

196196
response = requests.get(
197-
f"https://huggingface.co/datasets/{repo_id}/resolve/main/meta/episodes.jsonl"
197+
f"https://huggingface.co/datasets/{repo_id}/resolve/main/meta/episodes.jsonl", timeout=5
198198
)
199199
response.raise_for_status()
200200
# Split into lines and parse each line as JSON
@@ -318,7 +318,9 @@ def get_episode_language_instruction(dataset: LeRobotDataset, ep_index: int) ->
318318

319319

320320
def get_dataset_info(repo_id: str) -> IterableNamespace:
321-
response = requests.get(f"https://huggingface.co/datasets/{repo_id}/resolve/main/meta/info.json")
321+
response = requests.get(
322+
f"https://huggingface.co/datasets/{repo_id}/resolve/main/meta/info.json", timeout=5
323+
)
322324
response.raise_for_status() # Raises an HTTPError for bad responses
323325
dataset_info = response.json()
324326
dataset_info["repo_id"] = repo_id

lerobot/templates/visualize_dataset_template.html

+13-13
Original file line numberDiff line numberDiff line change
@@ -42,33 +42,33 @@ <h1 class="mb-4 text-xl font-semibold">{{ dataset_info.repo_id }}</h1>
4242
<ul>
4343
<template x-for="episode in paginatedEpisodes" :key="episode">
4444
<li class="font-mono text-sm mt-0.5">
45-
<a :href="'episode_' + episode"
45+
<a :href="'episode_' + episode"
4646
:class="{'underline': true, 'font-bold -ml-1': episode == {{ episode_id }}}"
4747
x-text="'Episode ' + episode"></a>
4848
</li>
4949
</template>
5050
</ul>
51-
51+
5252
<div class="flex items-center mt-3 text-xs" x-show="totalPages > 1">
53-
<button @click="prevPage()"
53+
<button @click="prevPage()"
5454
class="px-2 py-1 bg-slate-800 rounded mr-2"
5555
:class="{'opacity-50 cursor-not-allowed': page === 1}"
5656
:disabled="page === 1">
5757
&laquo; Prev
5858
</button>
5959
<span class="font-mono mr-2" x-text="` ${page} / ${totalPages}`"></span>
60-
<button @click="nextPage()"
60+
<button @click="nextPage()"
6161
class="px-2 py-1 bg-slate-800 rounded"
6262
:class="{'opacity-50 cursor-not-allowed': page === totalPages}"
6363
:disabled="page === totalPages">
6464
Next &raquo;
6565
</button>
6666
</div>
6767
</div>
68-
68+
6969
<!-- episodes menu for small screens -->
7070
<div class="flex overflow-x-auto md:hidden" x-data="episodePagination">
71-
<button @click="prevPage()"
71+
<button @click="prevPage()"
7272
class="px-2 bg-slate-800 rounded mr-2"
7373
:class="{'opacity-50 cursor-not-allowed': page === 1}"
7474
:disabled="page === 1">&laquo;</button>
@@ -83,7 +83,7 @@ <h1 class="mb-4 text-xl font-semibold">{{ dataset_info.repo_id }}</h1>
8383
</p>
8484
</template>
8585
</div>
86-
<button @click="nextPage()"
86+
<button @click="nextPage()"
8787
class="px-2 bg-slate-800 rounded ml-2"
8888
:class="{'opacity-50 cursor-not-allowed': page === totalPages}"
8989
:disabled="page === totalPages">&raquo; </button>
@@ -476,7 +476,7 @@ <h1 class="text-xl font-bold mt-4 font-mono">
476476
episodes: {{ episodes }},
477477
pageSize: 100,
478478
page: 1,
479-
479+
480480
init() {
481481
// Find which page contains the current episode_id
482482
const currentEpisodeId = {{ episode_id }};
@@ -485,23 +485,23 @@ <h1 class="text-xl font-bold mt-4 font-mono">
485485
this.page = Math.floor(episodeIndex / this.pageSize) + 1;
486486
}
487487
},
488-
488+
489489
get totalPages() {
490490
return Math.ceil(this.episodes.length / this.pageSize);
491491
},
492-
492+
493493
get paginatedEpisodes() {
494494
const start = (this.page - 1) * this.pageSize;
495495
const end = start + this.pageSize;
496496
return this.episodes.slice(start, end);
497497
},
498-
498+
499499
nextPage() {
500500
if (this.page < this.totalPages) {
501501
this.page++;
502502
}
503503
},
504-
504+
505505
prevPage() {
506506
if (this.page > 1) {
507507
this.page--;
@@ -515,7 +515,7 @@ <h1 class="text-xl font-bold mt-4 font-mono">
515515
window.addEventListener('keydown', (e) => {
516516
// Use the space bar to play and pause, instead of default action (e.g. scrolling)
517517
const { keyCode, key } = e;
518-
518+
519519
if (keyCode === 32 || key === ' ') {
520520
e.preventDefault();
521521
const btnPause = document.querySelector('[x-ref="btnPause"]');

pyproject.toml

+10-1
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,19 @@ exclude = [
111111
"venv",
112112
]
113113

114-
115114
[tool.ruff.lint]
116115
select = ["E4", "E7", "E9", "F", "I", "N", "B", "C4", "SIM"]
117116

117+
[tool.bandit]
118+
exclude_dirs = [
119+
"tests",
120+
"benchmarks",
121+
"lerobot/common/datasets/push_dataset_to_hub",
122+
"lerobot/common/datasets/v2/convert_dataset_v1_to_v2",
123+
"lerobot/common/policies/pi0/conversion_scripts",
124+
"lerobot/scripts/push_dataset_to_hub.py",
125+
]
126+
skips = ["B101", "B311", "B404", "B603"]
118127

119128
[tool.typos]
120129
default.extend-ignore-re = [

0 commit comments

Comments
 (0)