From 2a53537006d325d5c8436a215dd68833dd9cf91c Mon Sep 17 00:00:00 2001 From: Avinash Kumar Deepak Date: Thu, 12 Feb 2026 11:38:41 +0530 Subject: [PATCH 1/2] Add node label validation to prevent command injection (#251) From e0b44ee989ff1a1ae1fe696fdf63b88892c9242c Mon Sep 17 00:00:00 2001 From: Avinash Kumar Deepak Date: Thu, 12 Feb 2026 12:03:50 +0530 Subject: [PATCH 2/2] Reject node labels with shell metacharacters in CLI validate (#251) --- concore_cli/commands/validate.py | 5 +++++ tests/test_graph.py | 17 +++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/concore_cli/commands/validate.py b/concore_cli/commands/validate.py index fa1ea18..f8265b9 100644 --- a/concore_cli/commands/validate.py +++ b/concore_cli/commands/validate.py @@ -84,6 +84,11 @@ def validate_workflow(workflow_file, console): label = label_tag.text.strip() node_labels.append(label) + # reject shell metacharacters to prevent command injection (#251) + if re.search(r'[;&|`$\'"()\\]', label): + errors.append(f"Node '{label}' contains unsafe shell characters") + continue + if ':' not in label: warnings.append(f"Node '{label}' missing format 'ID:filename'") else: diff --git a/tests/test_graph.py b/tests/test_graph.py index 97102dc..f6e2825 100644 --- a/tests/test_graph.py +++ b/tests/test_graph.py @@ -112,6 +112,23 @@ def test_validate_node_missing_filename(self): self.assertIn('Validation failed', result.output) self.assertIn('has no filename', result.output) + def test_validate_unsafe_node_label(self): + content = ''' + + + + n0;rm -rf /:script.py + + + + ''' + filepath = self.create_graph_file('injection.graphml', content) + + result = self.runner.invoke(cli, ['validate', filepath]) + + self.assertIn('Validation failed', result.output) + self.assertIn('unsafe shell characters', result.output) + def test_validate_valid_graph(self): content = '''