Advisory-RSS - GitHub + CERT-TR (SGB)
Security-first local service that lists GitHub Security Advisories created/owned by you and CERT-TR / T.C. Siber Güvenlik Başkanlığı advisories received via e-mail (Proton Bridge or Gmail) and exposes them as a single mixed RSS 2.0 feed for Zen Browser's RSS Live Folder. What is 'Zen Browser's Live Folder?' == https://github.com/zen-browser/desktop/releases/tag/1.19b
flowchart LR
GH["GitHub API<br/>(PAT)"]
PB["Proton Bridge IMAP<br/><i>siberguvenlik.gov.tr</i><br/>BODY.PEEK — never marks read"]
GM["Gmail IMAP<br/><i>imap.gmail.com</i><br/>App Password / XOAUTH2<br/>never marks read"]
GH --> NORM["normalize + cache<br/>(advisories.db)"]
PB --> NORM
GM --> NORM
NORM --> RSS["RSS 2.0<br/>on 127.0.0.1"]
RSS --> ZEN["Zen Live Folder"]
style GH fill:#24292f,stroke:#1f2328,color:#fff
style PB fill:#6d28d9,stroke:#4c1d95,color:#fff
style GM fill:#dc2626,stroke:#991b1b,color:#fff
style NORM fill:#f59e0b,stroke:#92400e,color:#000
style RSS fill:#0ea5e9,stroke:#0c4a6e,color:#fff
style ZEN fill:#059669,stroke:#064e3b,color:#fff
Endpoints:
http://127.0.0.1:PORT/rss.xml # mixed (GitHub + CERT-TR)
http://127.0.0.1:PORT/rss.xml?source=github
http://127.0.0.1:PORT/rss.xml?source=cert-tr
http://127.0.0.1:PORT/health # per-source counts, cert_tr diag
http://127.0.0.1:PORT/ # hint
1. Prerequisites
- Python 3.12+
uvorpip+ venv- For GitHub source: a GitHub account that owns/creates advisories (you are
author) + PAT (see §3) - For CERT-TR source (optional,
ENABLE_CERT_TR=true):- Proton Mail with Bridge installed (paid plan required, you can patch the source though) or Gmail with IMAP enabled
- CERT-TR mails come from
cve@siberguvenlik.gov.tr/siberguvenlik.gov.tr- only CVE-assigned mails are ingested (likeCVE ID Talebi,Zafiyet Bildiriminiz Hakkındawithout CVE are skipped) - Proton: Bridge exposes localhost IMAP
127.0.0.1:1143STARTTLS(self-signed) - Gmail:
imap.gmail.com:993SSLvia App Password (16 chars, 2FA required) or OAuth 2.0 (google-auth+google-auth-oauthlib)
2. Installation
2.1 User Install
pip install advisory-rss
pipx install advisory-rss
2.2 Dev Install
git clone https://github.com/Lunixizm0/advisory-rss
cd advisory-rss
# with uv (recommended)
uv sync --extra dev
# or with pip
python -m venv .venv && source .venv/bin/activate
pip install -e .[dev]
# verify
app --help
app auth login --help
pytest -q # 78 tests
ruff check && pyright # All checks passed!
3. GitHub PAT
The service uses official GitHub REST API for the GitHub source.
| PAT type | Where to create | Scopes / Permissions required | When needed |
|---|---|---|---|
| Fine-grained PAT (recommended) | https://github.com/settings/personal-access-tokens/new | Resource owner: your user + relevant orgs - Repository access: All repositories (or select repos) - Repository permissions - Security advisories: Read-only + Metadata: Read-only (implied). For org-wide bulk fetch: Organization permissions - Security advisories: Read-only (requires org owner/security-manager). | Preferred - short expiry (30–90 days), no read to code. |
| Classic PAT fallback | https://github.com/settings/tokens/new | repo or at minimum public_repo (but private/draft advisories require repo). Docs: repo or repository_advisories:read (docs.github.com/en/rest/security-advisories/repository-advisories). |
If fine-grained is unavailable. Note: repo grants read to code - broader than needed. |
No other scopes are needed. Do not grant admin:org, delete_repo, workflow, etc.
GitHub API endpoints used:
GET /user- resolves authenticatedloginGET /user/repos?affiliation=owner&visibility=all&per_page=100&sort=updated- paginated enumerates repos you ownGET /user/orgs- lists orgs you belong toGET /orgs/{org}/security-advisories?per_page=100&sort=updated&state={triage,draft,published,closed}- org-wide bulk (requires owner/security-manager, else 403/404 and we fall back to per-repo)GET /repos/{owner}/{repo}/security-advisories?per_page=100&sort=updated&direction=desc&state={triage,draft,published,closed}- primary fetch, paginated viaLink: <…after=…>; rel="next"until exhaustionGET /advisories/{ghsa_id}- optional enrichment for published global view (not used for discovery)
Why GraphQL is rejected for ownership: docs.github.com/en/graphql/reference/security-advisories lists securityAdvisories{ghsaId,summary,severity,…} with args classifications, epss*, first/last, identifier, orderBy, publishedSince - no author field and no author filter, so it cannot identify "created by me" reliably. We use REST author.login and filter client-side.
4. CERT-TR / Gmail / Proton
4a. GitHub only (default)
cp .env.example .env
$EDITOR .env
# e.g. GITHUB_TOKEN=github_pat_… or ghp_…
# leave BIND_ADDRESS=127.0.0.1 and PORT=8765 - do NOT change to 0.0.0.0
# validate PAT (only checks GET /user, never saves to file - .env is the only source)
app auth login --provider github
# Paste PAT -> "+ Validated as @you" -> choose to write to .env or set manually
# manual fetch - writes cache/advisories.db
app sync
app sync --source github # only GitHub
app status
# - GitHub: 1 CERT-TR: 2 (if CERT-TR enabled)
Direct fetch for advisories in repos you don't own (you authored GHSA in other-org/other-repo but affiliation=owner doesn't list it - GitHub has no author filter, see Known Limitations):
# .env
GITHUB_REPOS=your-org/your-repo,other-org/other-repo # comma-separated, always scanned
GITHUB_ORG=your-org # expands via /orgs/{org}/repos
SKIP_FULL_SCAN=true # optional: skip scanning all owned repos, only scan GITHUB_REPOS/GITHUB_ORG (fast)
# PAT must have Repository access -> Selected repositories covering those repos (fine-grained)
LOG_LEVEL=INFO app sync
FILTER_MODE semantics, .env.example:22:
author(default) - onlyadvisory.author.login == your_login(precise "created by me")author_or_publisher- also matchespublisher.loginauthor_or_collaborator- also matchescollaborating_users[](covers advisories where you are collaborator but not author)
4b. CERT-TR via Proton Bridge
Bridge must be installed, logged in, and running (protonmail-bridge --cli - info shows host/port/password).
cp .env.example .env
$EDITOR .env
# interactive login (validates via IMAP SELECT, does not mark read)
app auth login --provider proton --email mail@mail.com
# Paste Bridge password -> "+ Proton IMAP doğrulandı"
# Writes PROTON_BRIDGE_EMAIL/PASSWORD (or appends to PROTON_BRIDGE_EMAILS) to .env
app sync --source cert-tr # only CERT-TR
app sync --source all # GitHub + CERT-TR mixed
app status # shows CERT-TR accounts: [proton] mail@mail.com -> folder=INBOX host=127.0.0.1:1143
Bridge's IMAP is 127.0.0.1:1143 STARTTLS with self-signed cert (CERT_NONE), BODY.PEEK + SELECT readonly=True (never sets \Seen), reconnect every 25 mails (Bridge drops).
4c. CERT-TR via Gmail (App Password or OAuth)
App Password (simplest, 2FA required):
- Gmail - Google Hesabı - Güvenlik - 2 Adımlı Doğrulama - Uygulama şifreleri -
Posta-Diğer-Advisory-RSS- 16 haneli şifre (örn.abcd efgh ijkl mnop, boşluklar korunur). - Gmail - Ayarlar - Yönlendirme ve POP/IMAP - IMAP'ı etkinleştir.
app auth login --provider gmail --method app-password --email mail@mail.com
# Paste App Password -> "+ Gmail IMAP (App Password) doğrulandı"
OAuth 2.0 (recommended for long-lived, no app password):
- https://console.cloud.google.com/ - Create Project - APIs & Services - Credentials - Create Credentials - OAuth Client ID - Application type: Desktop - Name:
Advisory-RSS- Create - copyClient ID/Client Secret. - Enable Gmail API: APIs & Services - Enable APIs - search
Gmail API- Enable. - The CLI will open browser for consent (
https://mail.google.com/scope,access_type=offlineprompt=consentto getrefresh_token).
app auth login --provider gmail --method oauth --email mail@mail.com
5. Starting the Server
app serve
# binds 127.0.0.1:8765, background refresh every REFRESH_INTERVAL (default 600s = 10 min) for BOTH sources
# health: curl http://127.0.0.1:8765/health | jq
# feed : curl http://127.0.0.1:8765/rss.xml | xmllint --noout -
# filter: curl "http://127.0.0.1:8765/rss.xml?source=cert-tr" | xmllint --noout -
6. RSS URL
Canonical for Zen Browser (mixed):
http://127.0.0.1:8765/rss.xml
http://127.0.0.1:8765/rss.xml?source=github
http://127.0.0.1:8765/rss.xml?source=cert-tr
Do not use HTTPS. Also, no auth on /rss.xml (Zen has no RSS auth). Mixed feed title: Security Advisories (GitHub + CERT-TR) - @you, per-source: [CERT-TR] pardus-etap-settings: CVE-2026-92083 (CWE-862).
7. Adding the Feed to Zen Browser RSS Dynamic Folder
- Start the feed:
app serveand verifycurl http://127.0.0.1:8765/rss.xml | headreturns<rss version="2.0">. - Open Zen Browser - Right Click - Live Folder - Add RSS Feed
- Paste
http://127.0.0.1:8765/rss.xmlas the feed source. Leave protocol HTTP (not HTTPS). - Save. Advisories appear sorted
updated_at DESC, newest first. Withdrawn advisories remain with[WITHDRAWN]prefix - not deleted. CERT-TR items have[CERT-TR]prefix, NVD link,source:cert-tr/cve:/cwe:categories. - If Zen shows empty folder:
curl http://127.0.0.1:8765/health | jq .advisories_count,.github_count,.cert_tr_countshould be >0; if 0, re-runapp syncand checkapp statusfor rate-limit/auth errors.
8. Changing the Refresh Interval
# .env
REFRESH_INTERVAL=300 # 5 minutes, min 60
# and optionally
MAX_ITEMS=500 # RSS truncation (cache still retains all to avoid missing advisories)
Restart app serve to apply. The feed Cache-Control: private, max-age=300, must-revalidate and <ttl>5</ttl> update automatically. app status shows Next scheduled sync. background_refresh_loop src/advisory_rss/server/app.py:346 polls both GitHub (If-None-Match/ETag) and CERT-TR (IMAP BODY.PEEK) every interval, asyncio.to_thread for IMAP, stale kept on error.
8b. Keep running after closing the terminal (--daemon)
Normal app serve dies when the terminal closes (SIGHUP). If you want it to keep running in the background:
# easiest - daemonize (double-fork + setsid, like nohup but with pid/log management)
app serve --daemon
# - pid: cache/advisory-rss.pid , log: cache/serve.log
# verification
cat cache/advisory-rss.pid
ps -p $(cat cache/advisory-rss.pid) -o pid,cmd
curl http://127.0.0.1:8765/health
tail -f cache/serve.log
app stop # SIGTERM + pid cleanup
app stop --pid-file cache/advisory-rss.pid
# alternatives (without daemon):
nohup app serve > cache/serve.log 2>&1 & disown
# or
tmux new -s rss "app serve"
# or systemd user service (persistent)
# ~/.config/systemd/user/advisory-rss.service:
# [Unit] Description=Advisory RSS localhost-only
# [Service] ExecStart=%h/Belgeler/Projeler/Advisory-RSS/.venv/bin/python -m advisory_rss.cli serve
# Restart=always
# Environment=GITHUB_TOKEN=ghp_...
# [Install] WantedBy=default.target
# systemctl --user daemon-reload && systemctl --user enable --now advisory-rss
Background behaviour: RSS reads cache only; a background task polls both sources every REFRESH_INTERVAL, uses If-None-Match/ETag for GitHub and BODY.PEEK/readonly=True for IMAP, and keeps stale cache on transient errors (requirement: feed stays available if GitHub/Gmail/Proton is down).
9. Troubleshooting
| Symptom | Check |
|---|---|
401 Unauthorized at app sync |
PAT expired/revoked or empty. Re-run app auth login --provider github; verify at https://github.com/settings/tokens. See Health last_error. |
403 Forbidden |
PAT scopes missing repository_advisories:read or org role insufficient (org bulk needs owner/security-manager - falls back to per-repo). Log shows scope hint. |
429 / rate limited |
health.rate_limited_until set, app status shows it. Wait or raise MAX_REPOS/reduce REFRESH_INTERVAL frequency. Logs include Retry-After/X-RateLimit-Reset. |
404 for a repo |
Repo not found or no advisories - skipped, not fatal. |
422 Validation |
GitHub rejected params (e.g., bad state) - logged and skipped. |
| Feed empty but advisories exist | Check FILTER_MODE (default author requires you are author. Try author_or_publisher). Also ensure authenticated_user in app status equals your advisory author. For CERT-TR: check ENABLE_CERT_TR=true and app status - CERT-TR accounts: N and IMAP search empty - folder name wrong? Try GMAIL_IMAP_FOLDERS=INBOX only, or check LOG_LEVEL=DEBUG app sync. |
IMAP login failed (Proton) |
Bridge running? 127.0.0.1:1143 reachable? protonmail-bridge --cli - info shows correct host/port/password. Password is Bridge password, not account password. Check PROTON_BRIDGE_HOST/PORT/SECURITY. |
IMAP login failed (Gmail App Password) |
2FA enabled? App Passwords - generate new 16-char (spaces preserved). Gmail - Settings - Forwarding and POP/IMAP - IMAP enabled. Check GMAIL_IMAP_HOST=imap.gmail.com:993 SSL. |
IMAP XOAUTH2 failed (Gmail OAuth) |
GMAIL_OAUTH_CLIENT_ID/SECRET correct? Refresh token expired/revoked? Re-run app auth login --provider gmail --method oauth. Check cache/gmail_oauth.json exists (chmod 600). Ensure Gmail API enabled in Google Cloud. Check LOG_LEVEL=DEBUG for fetch_access_token error. https://oauth2.googleapis.com/token must be reachable. |
UnicodeEncodeError: ascii ... Yazışmaları |
Fixed in src/advisory_rss/cert_tr/imap.py:24 via modified UTF-7 fallback + mail._encoding='utf-8' + ENABLE UTF8=ACCEPT. Ensure GMAIL_IMAP_FOLDERS uses , as separator (not ; + space split) and folder name exactly as in Gmail UI (case-sensitive). Try LOG_LEVEL=DEBUG app sync --source cert-tr to see IMAP select folder. |
CERT-TR sync: no advisories (raw 0) |
CERT_TR_SENDER_ALLOWLIST=siberguvenlik.gov.tr correct? Check IMAP search empty - folder empty or FROM mismatch. Try GMAIL_IMAP_FOLDERS=INBOX and check Gmail for mails from cve@siberguvenlik.gov.tr. CERT_TR_MAX_MAILS maybe too low? CERT_TR_SEARCH_DAYS maybe filtering? |
CERT-TR sync OK - 0 advisories ... parsed 0 but raw >0 |
All mails without CVE are now skipped (CVE-only). Check health - cert_tr_count should be 2 for your CVE-2026-92083/16245. Old CERT-TR-MSG-* rows auto-deleted on next CacheStore init src/advisory_rss/cache/store.py:76. |
pip-audit failure |
pip install pip-audit && pip-audit - fix by bumping pinned dep in pyproject.toml. |
google-auth-oauthlib missing |
uv sync --extra dev or pip install google-auth google-auth-oauthlib (added to pyproject.toml:9). |
View logs: LOG_LEVEL=DEBUG app serve for detail (still redacted).
Verify feed: xmllint --noout <(curl -s http://127.0.0.1:8765/rss.xml) - no output means valid. Check per-source: curl -s "http://127.0.0.1:8765/rss.xml?source=cert-tr" | grep CERT-TR.
Architecture Explanation
flowchart TD
subgraph GH["GitHub REST API — api.github.com"]
direction TB
GH_AUTH["PAT Bearer<br/>2022-11-28"]
GH_A1["get_user<br/>list_user_orgs<br/>list_user_repos"]
GH_A2["orgs/{org}/security-advisories<br/>(bulk, owner/security-manager)"]
GH_A3["repos/{owner}/{repo}/security-advisories<br/>per_page=100, paginated via Link header<br/>+ GITHUB_REPOS / GITHUB_ORG"]
GH_A4["HTTP handling<br/>401/403/404/422/429/5xx<br/>ETag / If-None-Match → 304"]
GH_A5["normalize<br/>filter by author<br/>FILTER_MODE: author / author_or_publisher / collaborator"]
GH_A6["dedup by GHSA<br/>sort updated_at DESC"]
GH_AUTH --> GH_A1
GH_A1 --> GH_A2
GH_A1 --> GH_A3
GH_A2 --> GH_A4
GH_A3 --> GH_A4
GH_A4 --> GH_A5 --> GH_A6
end
subgraph CERT["CERT-TR IMAP<br/>Proton 127.0.0.1:1143 / Gmail imap.gmail.com:993"]
direction TB
CT_AUTH["OAuth XOAUTH2<br/>refresh_token → access_token<br/>or App Password / Bridge"]
CT_B1["connect_imap() per account<br/>{email, host, port, security, auth_method}"]
CT_B2["_ssl_context_for_host()<br/>CERT_NONE: Bridge / CERT_REQUIRED: Gmail"]
CT_B3["_select_folder_imap()<br/>UTF-8 + ENABLE UTF8=ACCEPT<br/>modified UTF-7 fallback — CVE Yazışmaları"]
CT_B4["IMAP SEARCH<br/>FROM siberguvenlik.gov.tr [SINCE ...]<br/>per folder — readonly + BODY.PEEK"]
CT_B5["fetch BODY.PEEK[]<br/>batch 25 + reconnect"]
CT_B6["parse_cert_tr_email()<br/>src/advisory_rss/cert_tr/parser.py:285<br/>strict CVE-only, CWE / product / NVD refs"]
CT_B7["is_cert_tr_sender()<br/>allowlist check"]
CT_B8["dedup by CERT-TR-CVE-...<br/>sort"]
CT_AUTH --> CT_B1 --> CT_B2 --> CT_B3 --> CT_B4 --> CT_B5 --> CT_B6 --> CT_B7 --> CT_B8
end
AGG["aggregator<br/>mixed — no collision GHSA-* vs CERT-TR-*"]
CACHE["upsert — cache/advisories.db<br/>SQLite WAL, source column, ETag map, MSG cleanup"]
LOOP["background_refresh_loop<br/>asyncio every REFRESH_INTERVAL<br/>stale kept on error"]
REQ["RSS request<br/>cache only — ?source= filter"]
FEED["GET http://127.0.0.1:8765/rss.xml<br/>builder: [CERT-TR] / [HIGH]<br/>source:cert-tr / github, cve: / cwe: categories"]
ZEN["Zen Browser<br/>RSS Dynamic Folder"]
GH_A6 --> AGG
CT_B8 --> AGG
AGG --> CACHE
CACHE --> LOOP
CACHE --> REQ
LOOP -. poll & upsert .-> CACHE
REQ --> FEED --> ZEN
style GH fill:#24292f,stroke:#1f2328,color:#fff
style CERT fill:#1e3a5f,stroke:#0f172a,color:#fff
style AGG fill:#f59e0b,stroke:#92400e,color:#000
style CACHE fill:#eab308,stroke:#713f12,color:#000
style LOOP fill:#6366f1,stroke:#312e81,color:#fff
style REQ fill:#06b6d4,stroke:#164e63,color:#fff
style FEED fill:#0ea5e9,stroke:#0c4a6e,color:#fff
style ZEN fill:#059669,stroke:#064e3b,color:#fff
Key invariants: RSS reads cache only; GH enumeration is exhaustive; IMAP never sets \Seen; failures keep stale cache; CERT-TR strict CVE-only (hash fallback removed).
Required Scopes/Permissions (Recap)
- GitHub Fine-grained:
Repository security advisories: Read,Metadata: Read, (org bulk:Organization security advisories: Read) - GitHub Classic:
repo(orpublic_repofor public advisories only, but private/draft needrepo/repository_advisories:read) - Proton Bridge: Bridge must be running,
PROTON_BRIDGE_PASSWORDis Bridge-generated (Mailbox details), not account password, paid plan required - Gmail App Password: Google Account - 2FA - App Passwords -
GMAIL_APP_PASSWORD(16 chars, spaces preserved), IMAP enabled - Gmail OAuth: Google Cloud - OAuth Client ID (Desktop) -
GMAIL_OAUTH_CLIENT_ID/SECRET-app auth login --provider gmail --method oauth-refresh_tokenstored incache/gmail_oauth.json(600) +.env(GMAIL_OAUTH_REFRESH_TOKEN(S)), scopehttps://mail.google.com/, usesXOAUTH2src/advisory_rss/auth/gmail.py:1+src/advisory_rss/cert_tr/imap.py:65
Known Limitations
- GitHub No server-side "created by me" filter - all filtering is client-side after listing advisories per repo/state. Costs API calls (~1 per repo × 4 states + org bulk) and is rate-limited; mitigated with ETag 304, pagination caps, and background polling rather than per-RSS-call.
- GitHub Enumeration requires listing all owned repos (
GET /user/repos) - large accounts (thousands of repos) need many pages;MAX_REPOS/MAX_PAGES_PER_REPOcap prevents runaway,app statusreports caps hit. - GitHub Org bulk requires owner/security-manager - else 403/404 per org and we fall back to per-repo enumeration (expected).
- GitHub Global
GET /advisoriescannot tell ownership - it is the public advisory database; ignored for discovery, used only as optional enrichment if needed. - GHSA != chronological - must sort by
updated_at, not ID. - GraphQL
SecurityAdvisoryhas noauthor- verified; cannot replace REST for this use case. - Global enrichment 404 for draft/private - expected; we treat missing as not-enriched.
- Withdrawn state differs between global (
withdrawn_at/is_withdrawn) and repo (state: closed/withdrawn+withdrawn_at) - normalized into singlewithdrawn_at/state. - CERT-TR IMAP
FROMsearch is substring -FROM "siberguvenlik.gov.tr"is server-side substring, but finalis_cert_tr_sender()src/advisory_rss/cert_tr/parser.py:429does strict domain check; non-CVE mails are now skipped entirely. - Gmail/Proton folders with non-ASCII (e.g.,
CVE Yazışmaları) requiremodified UTF-7fallbacksrc/advisory_rss/cert_tr/imap.py:24;GMAIL_IMAP_FOLDERSmust be comma-separated (spaces preserved), not whitespace-split. - Gmail OAuth
refresh_tokenonly on first consent - ifrun_gmail_oauth_flowsrc/advisory_rss/auth/gmail.py:210returns norefresh_token, revoke access at https://myaccount.google.com/permissions and retry withprompt=consent. - Proton Bridge self-signed cert -
CERT_NONE+STARTTLS(orSSL); Gmail usesCERT_REQUIRED. - Legacy
CERT-TR-MSG-*rows - auto-deleted onCacheStoreinitsrc/advisory_rss/cache/store.py:76(non-CVE false positives).
Development & Tests
pytest -q # 78 tests (60 original + 14 CERT-TR + 4 Gmail)
pytest tests/unit -q -v
pytest tests/integration -v # starts ephemeral server on 127.0.0.1:0, validates RSS & headers
pytest tests/unit/test_cert_tr_settings.py tests/unit/test_cert_tr_imap.py -v # Gmail/Proton multi-folder, OAuth
pip-audit # audit scan
# Regenerate real fixtures from live GitHub API (uses GITHUB_TOKEN from .env, auto-detects GITHUB_REPOS/GITHUB_ORG/SKIP_FULL_SCAN)
python scripts/fixtures_generator.py
python scripts/fixtures_generator.py --ghsa GHSA-xxxx-xxxx-xxxx --repo bla/bla # single GHSA
# Lint / type-check (no noqa, truly fixed)
ruff check # All checks passed!
pyright # 0 errors, typeCheckingMode: standard, extraPaths: ["src"]
License
GNU
Metadata
Release files for advisory-rss 2.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| advisory_rss-2.2.0.tar.gz | 102.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| advisory_rss-2.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 193.7 kB
Release files / advisory_rss-2.2.0.tar.gz
| Download URL | advisory_rss-2.2.0.tar.gz |
|---|---|
| Size | 102.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
eb5a8e039cf2ee859b8c88df9a735b7c5b090df4a81fa2ef52681def3a65afa1
|
|
BLAKE2b-256 checksum How to use checksums |
a0b0c28e9221be7a226ea9e9e68d351db06b02f62396d408a94f6207345d33bd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 20, 2026.
Transparency logRelease files / advisory_rss-2.2.0-py3-none-any.whl
| Download URL | advisory_rss-2.2.0-py3-none-any.whl |
|---|---|
| Size | 91.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
373be40be76ec4b2403c358b45d89afd9caec93c0ece013037107ffcb8d834ca
|
|
BLAKE2b-256 checksum How to use checksums |
73acefd710608fe39a4aadf0253ed186c27fd4a6593a20761ca48a8c46d9284e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 20, 2026.
Transparency log