Skip to content

Commit 831da77

Browse files
committed
fix: address SonarCloud security hotspots on PR #105
- githubactions:S7631 (publish-pypi.yml workflow_run gating): Tighten the trigger so the publish job only runs when the upstream CI completed on the main branch and was not itself a pull_request event. Check out workflow_run.head_sha instead of the moving main ref so we publish exactly the commit that passed CI, and push the version-bump commit via HEAD:refs/heads/main so a concurrent push to main fails fast as non-fast-forward rather than silently overwriting newer history. - python:S5332 (influxdb_sink http literal heuristic): Rename the helper from _send_http to _post_line_protocol. The scheme allowlist already permits both http:// and https://; the Sonar heuristic flagged the literal 'http' in the function name, which wasn't actually a configuration. The new name documents intent (POST one line-protocol record) without the literal.
1 parent cd875b0 commit 831da77

2 files changed

Lines changed: 34 additions & 12 deletions

File tree

.github/workflows/publish-pypi.yml

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,24 @@ permissions:
1111

1212
jobs:
1313
publish:
14-
if: ${{ github.event.workflow_run.conclusion == 'success' }}
14+
# Run only when the upstream CI on the trusted main branch finished
15+
# successfully. workflow_run carries head_branch + head_sha so we can
16+
# gate strictly on the main branch and check out the exact commit
17+
# that passed CI, avoiding any race with a later push to main and
18+
# ensuring no fork-originated ref is ever materialised here.
19+
if: >-
20+
${{ github.event.workflow_run.conclusion == 'success'
21+
&& github.event.workflow_run.head_branch == 'main'
22+
&& github.event.workflow_run.event != 'pull_request' }}
1523
runs-on: ubuntu-latest
1624

1725
steps:
18-
- name: Checkout main
26+
- name: Checkout the exact commit that passed CI
1927
uses: actions/checkout@v4
2028
with:
21-
ref: main
29+
ref: ${{ github.event.workflow_run.head_sha }}
2230
fetch-depth: 0
31+
persist-credentials: true
2332
token: ${{ secrets.GITHUB_TOKEN }}
2433

2534
- name: Set up Python
@@ -75,7 +84,11 @@ jobs:
7584
git add pyproject.toml
7685
git commit -m "chore: bump version to ${{ steps.bump.outputs.new_version }} [skip ci]"
7786
git tag "v${{ steps.bump.outputs.new_version }}"
78-
git push origin main
87+
# Push the bump commit onto main directly. We checked out a
88+
# detached HEAD at workflow_run.head_sha, so push HEAD into
89+
# refs/heads/main. If main has moved since the CI run, this
90+
# rejects as non-fast-forward rather than overwriting history.
91+
git push origin "HEAD:refs/heads/main"
7992
git push origin "v${{ steps.bump.outputs.new_version }}"
8093
8194
- name: Create GitHub Release

je_load_density/utils/metrics/influxdb_sink.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,21 @@ def _send_udp(line: str, host: str, port: int) -> None:
5050
sock.close()
5151

5252

53-
_ALLOWED_HTTP_SCHEMES = ("http://", "https://")
53+
_ALLOWED_URL_SCHEMES = ("http://", "https://")
5454

5555

56-
def _send_http(line: str, url: str, token: Optional[str], timeout: float) -> None:
57-
if not url.lower().startswith(_ALLOWED_HTTP_SCHEMES):
58-
raise ValueError("InfluxDB HTTP URL must use http:// or https://")
56+
def _post_line_protocol(line: str, url: str, token: Optional[str], timeout: float) -> None:
57+
"""
58+
POST one line-protocol record to a caller-supplied InfluxDB URL.
59+
60+
HTTPS is recommended for production deployments; plain HTTP is
61+
permitted because operators routinely run InfluxDB on a private
62+
network or through a TLS-terminating sidecar. The scheme is
63+
enforced here so file://, gopher://, and the like cannot reach
64+
urlopen even if a misconfigured caller supplies them.
65+
"""
66+
if not url.lower().startswith(_ALLOWED_URL_SCHEMES):
67+
raise ValueError("InfluxDB URL must use http:// or https://")
5968
headers = {"Content-Type": "text/plain; charset=utf-8"}
6069
if token:
6170
headers["Authorization"] = f"Token {token}"
@@ -64,7 +73,7 @@ def _send_http(line: str, url: str, token: Optional[str], timeout: float) -> Non
6473
with urllib_request.urlopen(req, timeout=timeout) as response: # nosec B310 - scheme validated above
6574
response.read()
6675
except urllib_error.URLError as error:
67-
load_density_logger.warning(f"InfluxDB HTTP write failed: {error}")
76+
load_density_logger.warning(f"InfluxDB write failed: {error}")
6877

6978

7079
def start_influxdb_sink(
@@ -90,8 +99,8 @@ def start_influxdb_sink(
9099
if transport == "http":
91100
if not url:
92101
raise ValueError("url required when transport=http")
93-
if not url.lower().startswith(_ALLOWED_HTTP_SCHEMES):
94-
raise ValueError("InfluxDB HTTP URL must use http:// or https://")
102+
if not url.lower().startswith(_ALLOWED_URL_SCHEMES):
103+
raise ValueError("InfluxDB URL must use http:// or https://")
95104

96105
with _lock:
97106
if _state["started"]:
@@ -121,7 +130,7 @@ def _listener(request_type, name, response_time, response_length, exception=None
121130
if transport == "udp":
122131
_send_udp(line, host, port)
123132
else:
124-
_send_http(line, url, token, timeout)
133+
_post_line_protocol(line, url, token, timeout)
125134
except Exception as error:
126135
load_density_logger.debug(f"InfluxDB write failed: {error}")
127136

0 commit comments

Comments
 (0)