Skip to content

Commit 9b9131a

Browse files
authored
Merge pull request #1102 from common-workflow-language/bandit
turn on static security analysis using bandit
2 parents 875b928 + 896b6ae commit 9b9131a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

87 files changed

+101
-13172
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ MODULE=cwltool
2727
# `[[` conditional expressions.
2828
PYSOURCES=$(wildcard ${MODULE}/**.py tests/*.py) setup.py
2929
DEVPKGS=pycodestyle diff_cover autopep8 pylint coverage pydocstyle flake8 \
30-
pytest-xdist isort wheel -rtest-requirements.txt
30+
pytest-xdist==1.27.0 isort wheel -rtest-requirements.txt
3131
DEBDEVPKGS=pep8 python-autopep8 pylint python-coverage pydocstyle sloccount \
3232
python-flake8 python-mock shellcheck
3333
VERSION=1.0.$(shell TZ=UTC git log --first-parent --max-count=1 \

appveyor.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ install:
3232
- ps: 'Install-Product node 0.12 x64'
3333
- "set PATH=%PYTHON%\\Scripts;%PATH%"
3434
- "%PYTHON%\\python.exe -m pip install -U pip setuptools^>=20.3 wheel"
35-
- "%PYTHON%\\python.exe -m pip install -U codecov -rtest-requirements.txt pytest-xdist "
35+
- "%PYTHON%\\python.exe -m pip install -U codecov -rtest-requirements.txt pytest-xdist==1.27 "
3636
# Note the use of a `^` to escape the `>`
3737

3838
build_script:

cwltool/builder.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -207,13 +207,12 @@ def bind_input(self,
207207
value_from_expression = False
208208
if "inputBinding" in schema and isinstance(schema["inputBinding"], MutableMapping):
209209
binding = CommentedMap(schema["inputBinding"].items())
210-
assert binding is not None
211210

212211
bp = list(aslist(lead_pos))
213212
if "position" in binding:
214213
position = binding["position"]
215-
if isinstance(position, str): # no need to test the CWL Version
216-
# the schema for v1.0 only allow ints
214+
if isinstance(position, str): # no need to test the CWL Version
215+
# the schema for v1.0 only allow ints
217216
binding['position'] = self.do_eval(position, context=datum)
218217
bp.append(binding['position'])
219218
else:
@@ -238,7 +237,6 @@ def bind_input(self,
238237
avsc = self.names.get_name(t["name"], "")
239238
if not avsc:
240239
avsc = make_avsc_object(convert_to_dict(t), self.names)
241-
assert avsc is not None
242240
if validate.validate(avsc, datum):
243241
schema = copy.deepcopy(schema)
244242
schema["type"] = t
@@ -379,7 +377,6 @@ def tostr(self, value): # type: (Any) -> Text
379377
# docker_req is none only when there is no dockerRequirement
380378
# mentioned in hints and Requirement
381379
path = docker_windows_path_adjust(value["path"])
382-
assert path is not None
383380
return path
384381
return value["path"]
385382
else:
@@ -424,8 +421,7 @@ def generate_arg(self, binding): # type: (Dict[Text, Any]) -> List[Text]
424421
if sep:
425422
args.extend([prefix, self.tostr(j)])
426423
else:
427-
assert prefix is not None
428-
args.append(prefix + self.tostr(j))
424+
args.append("" if not prefix else prefix + self.tostr(j))
429425

430426
return [a for a in args if a is not None]
431427

cwltool/command_line_tool.py

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,8 @@ def revmap_file(builder, outdir, f):
157157
if "basename" not in f:
158158
f["basename"] = os.path.basename(path)
159159

160-
assert builder.pathmapper is not None
160+
if not builder.pathmapper:
161+
raise ValueError("Do not call revmap_file using a builder that doesn't have a pathmapper.")
161162
revmap_f = builder.pathmapper.reversemap(path)
162163

163164
if revmap_f and not builder.pathmapper.mapper(revmap_f[0]).type.startswith("Writable"):
@@ -204,7 +205,8 @@ def check_adjust(builder, file_o):
204205
doesn't reach everything in builder.bindings
205206
"""
206207

207-
assert builder.pathmapper is not None
208+
if not builder.pathmapper:
209+
raise ValueError("Do not call check_adjust using a builder that doesn't have a pathmapper.")
208210
file_o["path"] = docker_windows_path_adjust(
209211
builder.pathmapper.mapper(file_o["location"])[1])
210212
dn, bn = os.path.split(file_o["path"])
@@ -300,7 +302,7 @@ def job(self,
300302
if runtimeContext.cachedir and enableReuse:
301303
cachecontext = runtimeContext.copy()
302304
cachecontext.outdir = "/out"
303-
cachecontext.tmpdir = "/tmp"
305+
cachecontext.tmpdir = "/tmp" # nosec
304306
cachecontext.stagedir = "/stage"
305307
cachebuilder = self._init_job(job_order, cachecontext)
306308
cachebuilder.pathmapper = PathMapper(cachebuilder.files,
@@ -354,7 +356,8 @@ def job(self,
354356

355357
keydictstr = json_dumps(keydict, separators=(',', ':'),
356358
sort_keys=True)
357-
cachekey = hashlib.md5(keydictstr.encode('utf-8')).hexdigest()
359+
cachekey = hashlib.md5( # nosec
360+
keydictstr.encode('utf-8')).hexdigest()
358361

359362
_logger.debug("[job %s] keydictstr is %s -> %s", jobname,
360363
keydictstr, cachekey)
@@ -477,24 +480,24 @@ def rm_pending_output_callback(output_callbacks, jobcachepending,
477480
if self.tool.get("stdin"):
478481
with SourceLine(self.tool, "stdin", validate.ValidationException, debug):
479482
j.stdin = builder.do_eval(self.tool["stdin"])
480-
assert j.stdin is not None
481-
reffiles.append({"class": "File", "path": j.stdin})
483+
if j.stdin:
484+
reffiles.append({"class": "File", "path": j.stdin})
482485

483486
if self.tool.get("stderr"):
484487
with SourceLine(self.tool, "stderr", validate.ValidationException, debug):
485488
j.stderr = builder.do_eval(self.tool["stderr"])
486-
assert j.stderr is not None
487-
if os.path.isabs(j.stderr) or ".." in j.stderr:
488-
raise validate.ValidationException(
489-
"stderr must be a relative path, got '%s'" % j.stderr)
489+
if j.stderr:
490+
if os.path.isabs(j.stderr) or ".." in j.stderr:
491+
raise validate.ValidationException(
492+
"stderr must be a relative path, got '%s'" % j.stderr)
490493

491494
if self.tool.get("stdout"):
492495
with SourceLine(self.tool, "stdout", validate.ValidationException, debug):
493496
j.stdout = builder.do_eval(self.tool["stdout"])
494-
assert j.stdout is not None
495-
if os.path.isabs(j.stdout) or ".." in j.stdout or not j.stdout:
496-
raise validate.ValidationException(
497-
"stdout must be a relative path, got '%s'" % j.stdout)
497+
if j.stdout:
498+
if os.path.isabs(j.stdout) or ".." in j.stdout or not j.stdout:
499+
raise validate.ValidationException(
500+
"stdout must be a relative path, got '%s'" % j.stdout)
498501

499502
if debug:
500503
_logger.debug(u"[job %s] command line bindings is %s", j.name,
@@ -717,7 +720,7 @@ def collect_output(self,
717720
files["contents"] = content_limit_respected_read_bytes(f).decode("utf-8")
718721
if compute_checksum:
719722
with fs_access.open(rfile["location"], "rb") as f:
720-
checksum = hashlib.sha1()
723+
checksum = hashlib.sha1() # nosec
721724
contents = f.read(1024 * 1024)
722725
while contents != b"":
723726
checksum.update(contents)

cwltool/cwlrdf.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ def printrdf(wflow, ctx, style): # type: (Process, ContextType, Text) -> Text
2727
rdf = gather(wflow, ctx).serialize(format=style, encoding='utf-8')
2828
if not rdf:
2929
return u""
30-
assert rdf is not None
3130
return rdf.decode('utf-8')
3231

3332

cwltool/docker.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ def get_image(docker_requirement, # type: Dict[Text, Text]
155155
else:
156156
loadproc = subprocess.Popen(cmd, stdin=subprocess.PIPE,
157157
stdout=sys.stderr)
158-
assert loadproc.stdin is not None
158+
assert loadproc.stdin is not None # nosec
159159
_logger.info(u"Sending GET request to %s", docker_requirement["dockerLoad"])
160160
req = requests.get(docker_requirement["dockerLoad"], stream=True)
161161
size = 0
@@ -296,7 +296,8 @@ def create_runtime(self,
296296
runtime = [u"docker", u"run", u"-i"]
297297
self.append_volume(runtime, os.path.realpath(self.outdir),
298298
self.builder.outdir, writable=True)
299-
self.append_volume(runtime, os.path.realpath(self.tmpdir), "/tmp",
299+
tmpdir = "/tmp" # nosec
300+
self.append_volume(runtime, os.path.realpath(self.tmpdir), tmpdir,
300301
writable=True)
301302
self.add_volumes(self.pathmapper, runtime, any_path_okay=True,
302303
secret_store=runtimeContext.secret_store,

cwltool/executors.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -167,17 +167,17 @@ def run_jobs(self,
167167
self.output_dirs.add(job.outdir)
168168
if runtime_context.research_obj is not None:
169169
if not isinstance(process, Workflow):
170-
runtime_context.prov_obj = process.provenance_object
170+
prov_obj = process.provenance_object
171171
else:
172-
runtime_context.prov_obj = job.prov_obj
173-
assert runtime_context.prov_obj
174-
runtime_context.prov_obj.evaluate(
175-
process, job, job_order_object,
176-
runtime_context.research_obj)
177-
process_run_id =\
178-
runtime_context.prov_obj.record_process_start(
179-
process, job)
180-
runtime_context = runtime_context.copy()
172+
prov_obj = job.prov_obj
173+
if prov_obj:
174+
runtime_context.prov_obj = prov_obj
175+
prov_obj.evaluate(
176+
process, job, job_order_object,
177+
runtime_context.research_obj)
178+
process_run_id =\
179+
prov_obj.record_process_start(process, job)
180+
runtime_context = runtime_context.copy()
181181
runtime_context.process_run_id = process_run_id
182182
job.run(runtime_context)
183183
else:

cwltool/expression.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -261,8 +261,8 @@ def do_eval(ex, # type: Union[Text, Dict]
261261
): # type: (...) -> Any
262262

263263
runtime = copy.deepcopy(resources) # type: Dict[str, Any]
264-
runtime["tmpdir"] = docker_windows_path_adjust(tmpdir)
265-
runtime["outdir"] = docker_windows_path_adjust(outdir)
264+
runtime["tmpdir"] = docker_windows_path_adjust(tmpdir) if tmpdir else None
265+
runtime["outdir"] = docker_windows_path_adjust(outdir) if outdir else None
266266

267267
rootvars = {
268268
u"inputs": jobinput,
@@ -274,8 +274,7 @@ def do_eval(ex, # type: Union[Text, Dict]
274274
if six.PY3:
275275
rootvars = bytes2str_in_dicts(rootvars) # type: ignore
276276

277-
if needs_parsing(ex):
278-
assert isinstance(ex, string_types)
277+
if isinstance(ex, string_types) and needs_parsing(ex):
279278
fullJS = False
280279
jslib = u""
281280
for r in reversed(requirements):

cwltool/job.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -257,10 +257,14 @@ def _execute(self,
257257
u' 2> %s' % os.path.join(self.outdir, self.stderr) if self.stderr else '')
258258
if self.joborder is not None and runtimeContext.research_obj is not None:
259259
job_order = self.joborder
260-
assert runtimeContext.process_run_id is not None
261-
assert runtimeContext.prov_obj is not None
262-
runtimeContext.prov_obj.used_artefacts(
263-
job_order, runtimeContext.process_run_id, str(self.name))
260+
if runtimeContext.process_run_id is not None \
261+
and runtimeContext.prov_obj is not None:
262+
runtimeContext.prov_obj.used_artefacts(
263+
job_order, runtimeContext.process_run_id, str(self.name))
264+
else:
265+
_logger.warning("research_obj set but one of process_run_id "
266+
"or prov_obj is missing from runtimeContext: "
267+
"{}". format(runtimeContext))
264268
outputs = {} # type: MutableMapping[Text,Any]
265269
try:
266270
stdin_path = None
@@ -323,10 +327,13 @@ def _execute(self,
323327
processStatus = "permanentFail"
324328

325329
if 'listing' in self.generatefiles:
326-
assert self.generatemapper is not None
327-
relink_initialworkdir(
328-
self.generatemapper, self.outdir, self.builder.outdir,
329-
inplace_update=self.inplace_update)
330+
if self.generatemapper:
331+
relink_initialworkdir(
332+
self.generatemapper, self.outdir, self.builder.outdir,
333+
inplace_update=self.inplace_update)
334+
else:
335+
raise ValueError("'lsiting' in self.generatefiles but no "
336+
"generatemapper was setup.")
330337

331338
outputs = self.collect_outputs(self.outdir, rcode)
332339
outputs = bytes2str_in_dicts(outputs) # type: ignore

cwltool/load_tool.py

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -108,22 +108,18 @@ def fetch_document(argsworkflow, # type: Union[Text, Dict[Text, Any]]
108108
if loadingContext.loader is None:
109109
loadingContext.loader = default_loader(loadingContext.fetcher_constructor)
110110

111-
uri = None # type: Optional[Text]
112-
workflowobj = None # type: Optional[CommentedMap]
113111
if isinstance(argsworkflow, string_types):
114112
uri, fileuri = resolve_tool_uri(argsworkflow,
115113
resolver=loadingContext.resolver,
116114
document_loader=loadingContext.loader)
117115
workflowobj = loadingContext.loader.fetch(fileuri)
118-
elif isinstance(argsworkflow, dict):
116+
return loadingContext, workflowobj, uri
117+
if isinstance(argsworkflow, dict):
119118
uri = argsworkflow["id"] if argsworkflow.get("id") else "_:" + Text(uuid.uuid4())
120119
workflowobj = cast(CommentedMap, cmap(argsworkflow, fn=uri))
121120
loadingContext.loader.idx[uri] = workflowobj
122-
else:
123-
raise ValidationException("Must be URI or object: '%s'" % argsworkflow)
124-
assert workflowobj is not None
125-
126-
return loadingContext, workflowobj, uri
121+
return loadingContext, workflowobj, uri
122+
raise ValidationException("Must be URI or object: '%s'" % argsworkflow)
127123

128124

129125
def _convert_stdstreams_to_files(workflowobj):
@@ -152,10 +148,9 @@ def _convert_stdstreams_to_files(workflowobj):
152148
filename = workflowobj[streamtype]
153149
else:
154150
filename = Text(
155-
hashlib.sha1(json_dumps(workflowobj,
156-
sort_keys=True
157-
).encode('utf-8')
158-
).hexdigest())
151+
hashlib.sha1( # nosec
152+
json_dumps(workflowobj, sort_keys=True
153+
).encode('utf-8')).hexdigest())
159154
workflowobj[streamtype] = filename
160155
out['type'] = 'File'
161156
out['outputBinding'] = cmap({'glob': filename})

0 commit comments

Comments
 (0)