Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ProductReleaseAnnouncement/.gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
release.md
release.html
release-slack.txt
release-notes-*.md
venv/
__pycache__/
.pytest_cache/
2 changes: 1 addition & 1 deletion ProductReleaseAnnouncement/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ test: $(VENV)

.PHONY: clean
clean:
rm -rf $(VENV) .pytest_cache release.md release.html release-slack.txt
rm -rf $(VENV) .pytest_cache release.md release.html release-notes-*.md
4 changes: 2 additions & 2 deletions ProductReleaseAnnouncement/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,15 @@ source venv/bin/activate
./product_rel_announcement.py --markdown --operator snr,far
```

Output files: `release.md`, `release.html`, `release-slack.txt`.
Output files: `release.md`, `release.html`, `release-notes-<ver>.md`.

### Options

| Flag | Description |
|------|-------------|
| `--markdown` | Write `release.md` |
| `--html` | Write `release.html` |
| `--slack` | Write `release-slack.txt` (requires `--rhwa-version`) |
| `--slack` | Write `release-notes-<ver>.md` (requires `--rhwa-version`) |
| `--rhwa-version=<ver>` | RHWA release version (e.g. `4.21-0`) |
| `--slack-changes=<file>` | File with curated notable changes for Slack (one per line). Falls back to GitHub |
| `--operator=<ops>` | Comma-separated operator keys: `nmo`, `nhc`, `snr`, `far`, `mdr`, `sbr` |
Expand Down
15 changes: 8 additions & 7 deletions ProductReleaseAnnouncement/product_rel_announcement.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
Options:
-m, --markdown Write the upstream (Google Group) announcement to release.md
-w, --html Write the upstream (Google Group) announcement to release.html
-s, --slack Write the internal (Slack #forum-ocp-workload-availability) announcement to release-slack.txt
-s, --slack Write the internal (Slack) announcement to release-notes-<ver>.md
--rhwa-version=<ver> RHWA release version (e.g. 4.21-0), required with --slack
--slack-changes=<file> File with curated notable changes for Slack (one per line). Falls back to GitHub
--operator=<ops> Comma-separated operator keys to include (e.g. snr,far). Default: all
Expand All @@ -28,7 +28,7 @@
{"key": "snr", "name": "Self Node Remediation (SNR)", "repo": "self-node-remediation"},
{"key": "far", "name": "Fence Agents Remediation (FAR)", "repo": "fence-agents-remediation"},
{"key": "mdr", "name": "Machine Deletion Remediation (MDR)", "repo": "machine-deletion-remediation"},
{"key": "sbr", "name": "Storage Based Remediation (SBR)", "repo": "storage-based-remediation"},
{"key": "sbr", "name": "Storage-Based Remediation (SBR)", "repo": "storage-based-remediation"},
{"key": "nmo", "name": "Node Maintenance Operator (NMO)", "repo": "node-maintenance-operator"},
]

Expand Down Expand Up @@ -77,15 +77,15 @@ def main():
with open(arguments['--slack-changes'], 'r', encoding='utf-8') as f:
curated_changes = [line.strip() for line in f if line.strip()]
slack = build_slack_template(releases, arguments['--rhwa-version'], curated_changes)
with open('release-slack.txt', 'w', encoding='utf-8') as f:
slack_file = f"release-notes-{arguments['--rhwa-version']}.md"
with open(slack_file, 'w', encoding='utf-8') as f:
f.write(slack)
Comment on lines +80 to 82

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Validate rhwa-version before using it in a filesystem path.

rhwa-version is CLI-controlled and is interpolated directly into the filename. Values containing path separators can create unexpected nested paths, fail with FileNotFoundError, or—when matching directories already exist—escape the working directory and overwrite another writable file. Validate the expected format (for example, ^\d+\.\d+-\d+$) before constructing the path.

Proposed fix
+    version = arguments['--rhwa-version']
+    if not re.fullmatch(r'\d+\.\d+-\d+', version):
+        sys.exit("Error: invalid --rhwa-version")
+
-        slack_file = f"release-notes-{arguments['--rhwa-version']}.md"
+        slack_file = f"release-notes-{version}.md"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
slack_file = f"release-notes-{arguments['--rhwa-version']}.md"
with open(slack_file, 'w', encoding='utf-8') as f:
f.write(slack)
version = arguments['--rhwa-version']
if not re.fullmatch(r'\d+\.\d+-\d+', version):
sys.exit("Error: invalid --rhwa-version")
slack_file = f"release-notes-{version}.md"
with open(slack_file, 'w', encoding='utf-8') as f:
f.write(slack)
🧰 Tools
🪛 ast-grep (0.44.1)

[warning] 80-80: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(slack_file, 'w', encoding='utf-8')
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').

(open-filename-from-request)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ProductReleaseAnnouncement/product_rel_announcement.py` around lines 80 - 82,
Validate arguments['--rhwa-version'] against the expected version format (for
example, digits.digits-digits) before constructing slack_file in the release
announcement flow. Reject invalid values, including path separators, and only
then interpolate the validated version into the filename used by open.

Source: Linters/SAST tools



def build_upstream_template(releases):
lines = [
"On behalf of the Medik8s team, I am pleased to announce a new round of releases",
"for our operators. All releases are now available on the Kubernetes OperatorHub",
"and OKD.",
"The Medik8s team is pleased to announce a new round of releases for our operators.",
"All releases are now available on the Kubernetes OperatorHub and OKD.",
"",
"The release consists of these operators:",
"",
Expand All @@ -98,7 +98,8 @@ def build_upstream_template(releases):
lines.append(r['link'])
lines.append("")
lines.append("For more, visit our website https://www.medik8s.io/, contribute on GitHub")
lines.append("https://github.com/medik8s, and DM for more.")
lines.append("https://github.com/medik8s, join our mailing list https://groups.google.com/g/medik8s,")
lines.append("and follow us on LinkedIn https://www.linkedin.com/company/medik8s.")
lines.append("")
return "\n".join(lines)

Expand Down
8 changes: 4 additions & 4 deletions ProductReleaseAnnouncement/test_product_rel_announcement.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,8 @@ def test_no_notable_changes_section(self):
class TestBuildUpstreamTemplate:
def test_full_message(self):
expected = (
"On behalf of the Medik8s team, I am pleased to announce a new round of releases\n"
"for our operators. All releases are now available on the Kubernetes OperatorHub\n"
"and OKD.\n"
"The Medik8s team is pleased to announce a new round of releases for our operators.\n"
"All releases are now available on the Kubernetes OperatorHub and OKD.\n"
"\n"
"The release consists of these operators:\n"
"\n"
Expand All @@ -88,7 +87,8 @@ def test_full_message(self):
"https://github.com/medik8s/fence-agents-remediation/releases/tag/v0.8.0\n"
"\n"
"For more, visit our website https://www.medik8s.io/, contribute on GitHub\n"
"https://github.com/medik8s, and DM for more.\n"
"https://github.com/medik8s, join our mailing list https://groups.google.com/g/medik8s,\n"
"and follow us on LinkedIn https://www.linkedin.com/company/medik8s.\n"
)
assert build_upstream_template(FAKE_RELEASES) == expected

Expand Down