Skip to content

Commit 2c8d289

Browse files
committed
Add automated security scanning and harden release pipeline
- Dependabot: weekly automated PRs for Python deps and Actions pins - CodeQL: SAST on push/PR/weekly, results in GitHub Security tab - pip-audit: dependency CVE scan on push/PR/weekly (security.yml) and as a hard gate in publish.yml — a vulnerable dep now blocks PyPI release - detect-secrets: pre-commit hook to catch hard-coded credentials - SECURITY.md: published security policy with private vulnerability reporting - publish.yml: bumped checkout/setup-python to @v6 for consistency
1 parent bfde28f commit 2c8d289

9 files changed

Lines changed: 320 additions & 3 deletions

File tree

.github/dependabot.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: "pip"
4+
directory: "/"
5+
schedule:
6+
interval: "weekly"
7+
day: "monday"
8+
groups:
9+
minor-and-patch:
10+
update-types: ["minor", "patch"]
11+
open-pull-requests-limit: 5
12+
labels: ["dependencies"]
13+
14+
- package-ecosystem: "github-actions"
15+
directory: "/"
16+
schedule:
17+
interval: "weekly"
18+
day: "monday"
19+
labels: ["dependencies", "github-actions"]

.github/workflows/codeql.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: CodeQL
2+
3+
on:
4+
push:
5+
branches: [main, develop]
6+
pull_request:
7+
branches: [main]
8+
schedule:
9+
- cron: "0 6 * * 1"
10+
11+
jobs:
12+
analyze:
13+
name: Analyze (python)
14+
runs-on: ubuntu-latest
15+
permissions:
16+
actions: read
17+
contents: read
18+
security-events: write
19+
20+
steps:
21+
- uses: actions/checkout@v6
22+
23+
- name: Initialize CodeQL
24+
uses: github/codeql-action/init@v3
25+
with:
26+
languages: python
27+
28+
- name: Autobuild
29+
uses: github/codeql-action/autobuild@v3
30+
31+
- name: Perform CodeQL Analysis
32+
uses: github/codeql-action/analyze@v3
33+
with:
34+
category: "/language:python"

.github/workflows/publish.yml

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,25 @@ jobs:
1313
id-token: write # required for OIDC trusted publishing
1414

1515
steps:
16-
- uses: actions/checkout@v4
16+
- uses: actions/checkout@v6
1717

18-
- uses: actions/setup-python@v5
18+
- uses: actions/setup-python@v6
1919
with:
2020
python-version: "3.12"
2121

22+
- name: Install Poetry
23+
uses: snok/install-poetry@v1
24+
with:
25+
version: 2.4.1
26+
27+
- name: Export requirements
28+
run: poetry export --without-hashes -f requirements.txt -o /tmp/requirements.txt
29+
30+
- name: Audit dependencies
31+
uses: pypa/gh-action-pip-audit@v1.1.0
32+
with:
33+
inputs: /tmp/requirements.txt
34+
2235
- name: Install build
2336
run: pip install build
2437

.github/workflows/security.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: Security
2+
3+
on:
4+
push:
5+
branches: [main, develop]
6+
pull_request:
7+
branches: [main]
8+
schedule:
9+
- cron: "0 6 * * 1"
10+
11+
jobs:
12+
pip-audit:
13+
name: Dependency Vulnerability Scan
14+
runs-on: ubuntu-latest
15+
16+
steps:
17+
- uses: actions/checkout@v6
18+
19+
- name: Set up Python
20+
uses: actions/setup-python@v6
21+
with:
22+
python-version: "3.12"
23+
24+
- name: Install Poetry
25+
uses: snok/install-poetry@v1
26+
with:
27+
version: 2.4.1
28+
virtualenvs-create: true
29+
virtualenvs-in-project: true
30+
31+
- name: Install dependencies
32+
run: poetry install --no-interaction --no-root
33+
34+
- name: Export requirements
35+
run: poetry export --without-hashes -f requirements.txt -o /tmp/requirements.txt
36+
37+
- name: Run pip-audit
38+
uses: pypa/gh-action-pip-audit@v1.1.0
39+
with:
40+
inputs: /tmp/requirements.txt

.pre-commit-config.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,9 @@ repos:
4646
- id: bandit
4747
args: [-c, pyproject.toml]
4848
additional_dependencies: ["bandit[toml]"]
49+
50+
- repo: https://github.com/Yelp/detect-secrets
51+
rev: v1.5.0
52+
hooks:
53+
- id: detect-secrets
54+
args: ["--baseline", ".secrets.baseline"]

.secrets.baseline

Lines changed: 146 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
77

88
---
99

10+
## [0.3.6] - 2026-07-10
11+
12+
### Added
13+
14+
- Security hardening for the repository and release pipeline:
15+
- **Dependabot** (`.github/dependabot.yml`): weekly automated PRs for Python dependency and GitHub Actions updates; minor and patch updates grouped to reduce noise.
16+
- **CodeQL** (`.github/workflows/codeql.yml`): SAST scanning on every push, PR, and weekly schedule; results surface in the GitHub Security tab.
17+
- **Dependency vulnerability scanning** (`.github/workflows/security.yml`): `pip-audit` checks all locked dependencies against OSV/PyPI advisory databases on push, PR, and weekly.
18+
- **Publish gate** (`publish.yml`): `pip-audit` now runs before every PyPI release; a known-vulnerable dependency blocks the publish job.
19+
- **Secret detection** (`.pre-commit-config.yaml`): `detect-secrets` pre-commit hook blocks commits containing hard-coded credentials.
20+
- **`SECURITY.md`**: published security policy with private vulnerability reporting instructions and scope definition.
21+
22+
---
23+
1024
## [0.3.5] - 2026-07-07
1125

1226
### Changed

SECURITY.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Security Policy
2+
3+
## Supported Versions
4+
5+
| Version | Supported |
6+
| ------- | --------- |
7+
| Latest | Yes |
8+
| Older | No |
9+
10+
Only the latest published release receives security fixes. We recommend always pinning to the latest version.
11+
12+
## Reporting a Vulnerability
13+
14+
**Do not open a public GitHub issue for security vulnerabilities.**
15+
16+
Use GitHub's private vulnerability reporting:
17+
18+
1. Go to the [Security tab](https://github.com/ActiveCampaign/postmark-python/security)
19+
2. Click **"Report a vulnerability"**
20+
3. Fill in the details and submit
21+
22+
You'll receive an acknowledgement within **48 hours** and a triage response within **7 days**.
23+
24+
## Scope
25+
26+
**In scope:**
27+
- Vulnerabilities in this SDK's Python code
28+
- Vulnerable transitive dependencies pulled in by this package
29+
30+
**Out of scope:**
31+
- Bugs in the Postmark service or API itself — report those to [Postmark support](https://postmarkapp.com/support)
32+
- Issues requiring a compromised Postmark API token (treat tokens as secrets)
33+
- Vulnerabilities in your application code that happens to use this SDK
34+
35+
## Responsible Disclosure
36+
37+
We ask that you:
38+
- Give us reasonable time to fix the issue before public disclosure
39+
- Avoid accessing or modifying data belonging to other users
40+
- Not perform denial-of-service attacks
41+
42+
We commit to:
43+
- Acknowledge your report promptly
44+
- Keep you informed of our progress
45+
- Credit you in the release notes (unless you prefer otherwise)

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "postmark-python"
3-
version = "0.3.5"
3+
version = "0.3.6"
44
description = "The Official Postmark Python SDK."
55
authors = [
66
{ name = "Greg Svoboda", email = "gsvoboda@activecampaign.com" },

0 commit comments

Comments
 (0)