Repository: Kira-Pgr/Github-CVE-Listener
Branch: main
Commit: ab3373679037
Files: 5
Total size: 21.5 KB
Directory structure:
gitextract_nb9paz5w/
├── .github/
│ └── workflows/
│ └── AutoRun.yml
├── Github-CVE-Listener.py
├── LICENSE
├── README.md
└── README_ZH.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/AutoRun.yml
================================================
# This workflow will install Python dependencies, run tests and lint with a single version of Python
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
name: CVE-Monitor
on:
release:
types: [published]
push:
tags:
- 'v*'
#currently the workflow is set to run every 10 minutes
schedule:
- cron: '0/10 * * * *'
watch:
types: [started]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python 3.9
uses: actions/setup-python@v2
with:
python-version: 3.9
- name: Install dependencies
run: |
pip install requests
pip install PyNaCl
pip install lxml
pip install python-telegram-bot
- name: Monitor CVE
env:
SCKEY: ${{ secrets.SCKEY }}
TG_CHAT_ID: ${{ secrets.TG_CHAT_ID }}
TG_TOKEN: ${{ secrets.TG_TOKEN }}
total_count: ${{ secrets.TOTAL_COUNT }}
option: ${{ secrets.Option }}
GH_TOKEN: ${{ secrets.GH_TOKEN }}
GH_REPO: ${{ github.repository }}
run: |
python Github-CVE-Listener.py
================================================
FILE: Github-CVE-Listener.py
================================================
#coding = utf-8
import urllib
import requests,re,time
import html
import json
import os
from base64 import b64encode
from nacl import encoding, public
from lxml import etree
import telegram
import asyncio
import time
gh_token=os.getenv('GH_TOKEN')
gh_repo=os.getenv('GH_REPO')
#The option of send method
# 1 --> Wechat
# 2 --> TGBot
option=os.getenv('option')
Auth=r'token '+gh_token
geturl=r'https://api.github.com/repos/'+gh_repo+r'/actions/secrets/public-key'
#有道翻译API
def translate(text):
url = 'https://aidemo.youdao.com/trans'
try:
data = {"q": text, "from": "auto", "to": "zh-CHS"}
resp = requests.post(url, data)
if resp is not None and resp.status_code == 200:
respJson = json.loads(resp.text)
if "translation" in respJson:
text ="\n".join('' + str(i) for i in respJson["translation"])
except:
print("[WARN] Error translating message!")
return text
def getpublickey(Auth,geturl):
headers={'Accept': 'application/vnd.github.v3+json','Authorization': Auth}
html = requests.get(geturl,headers=headers)
jsontxt = json.loads(html.text)
if 'key' in jsontxt:
print("[INFO] Get public key suceeded")
else:
print("[ERROR] Get public key failed :( Is secret GH_TOKEN set correctly? ")
public_key = jsontxt['key']
global key_id
key_id = jsontxt['key_id']
return public_key
#encrypt secret
def createsecret(public_key,secret_value):
public_key = public.PublicKey(public_key.encode("utf-8"), encoding.Base64Encoder())
sealed_box = public.SealedBox(public_key)
encrypted = sealed_box.encrypt(str(secret_value).encode("utf-8"))
return b64encode(encrypted).decode("utf-8")
#upload total_count as secret
def setsecret(encrypted_value,key_id,puturl):
headers={'Accept': 'application/vnd.github.v3+json','Authorization': Auth}
data_str=r'{"encrypted_value":"'+encrypted_value+r'",'+r'"key_id":"'+key_id+r'"}'
putstatus=requests.put(puturl,headers=headers,data=data_str)
if putstatus.status_code >= 300:
print("[ERROR] total_count upload failed!")
else:
print("[INFO] total_count upload suceeded!")
return putstatus
#get cve related repos
def getNews():
try:
api = "https://api.github.com/search/repositories?q=CVE-2023&sort=updated"
headers = {
"Authorization": "Bearer "+gh_token
}
req = requests.get(api, headers=headers).text
respJson = json.loads(req)
#print(respJson)
#cve_total_count=re.findall ('"total_count":*.{1,10}"incomplete_results"',req)[0][14:17]
cve_total_count=respJson["total_count"]
#cve_description=re.findall ('"description":*.{1,200}"fork"',req)[0].replace("\",\"fork\"",'').replace("\"description\":\"",'')
if respJson["items"][0]["description"]:
cve_description = respJson["items"][0]["description"]
else:
cve_description = "NULL!"
#cve_url=re.findall ('"svn_url":*.{1,200}"homepage"',req)[0].replace("\",\"homepage\"",'').replace("\"svn_url\":\"",'')
cve_url = respJson["items"][0]["svn_url"]
return cve_total_count,cve_description,cve_url
except Exception as e:
print ("[ERROR] ",e,"Can not connect to github :( ")
#check CVE_ID
def exist_cve(cve):
query_cve_url = "https://cve.mitre.org/cgi-bin/cvename.cgi?name=" + cve
github_headers = {'Authorization': Auth }
response = requests.get(query_cve_url, headers=github_headers, timeout=10)
html = etree.HTML(response.text)
#des = html.xpath('//*[@id="GeneratedTable"]/table//tr[4]/td/text()')[0].strip()
if re.findall('but the record does not exist', str(html), flags=re.IGNORECASE):
print("[WARN] CVE_ID doesn't exist, skipping...")
return 0
else:
return 1
#get vuln description from CVE
def get_cve_des(cve):
try:
time.sleep(3)
query_cve_url = "https://www.cve.org/api/?action=getCveById&cveId=" + cve
print(query_cve_url)
github_headers = {
'Authorization': Auth }
#response = requests.get(query_cve_url, headers=github_headers, timeout=10)
#html = etree.HTML(response.text)
#des = html.xpath('//*[@id="GeneratedTable"]/table//tr[4]/td/text()')[0].strip()
resp = requests.get(query_cve_url,headers=github_headers, timeout=10)
respJson = json.loads(resp.text)
des = respJson["containers"]["cna"]["descriptions"][0]["value"]
return des
except Exception as e:
err = "* **RESERVED** *"
print("[WARN] Get CVE description Failed, cause CVE refused")
return err
#get cve id
def getid(respJson):
cve_name = respJson["items"][0]["name"]
cve_id = re.findall('(CVE\-\d+\-\d+)', cve_name, flags=re.IGNORECASE)
des = respJson["items"][0]["description"]
if des:
cve_des = re.findall('(CVE\-\d+\-\d+)', des, flags=re.IGNORECASE)
# if empty or have README only
if(int(respJson["items"][0]["size"]) == 0):
print("[WARN] Repo is empty or only contains readme...Skipping...")
exit(0)
readme = "https://raw.githubusercontent.com/" + str(respJson["items"][0]["full_name"]) + "/main/README.md"
readme_content = requests.get(readme).text
if str(cve_id) == "[]":
cve_id = cve_id + re.findall('(CVE\-\d+\-\d+)', readme_content, flags=re.IGNORECASE)
if str(cve_id) != "[]":
if("cve" in str(cve_id[0])):
return re.sub("cve", "CVE", str(cve_id[0]))
return cve_id[0]
else:
print("[WARN] Get CVE ID Failed, Does the repo contain the correct info?")
exit(0)
#Send TG
async def TG(cve_des):
text = r'喵~~ Senpai! 有新的CVE更新送达!'
msg ="CVE相关项目总数: " + str(getNews()[0]) + "\r\n" +"GitHub项目介绍: " + getNews()[1]+ "\r\n" +"("+translate(getNews()[1])+")"+"\r\n"+ "链接: " + getNews()[2] + "\r\n" + "该CVE编号的详情: " + cve_des +"\r\n"+"("+translate(cve_des)+")"+"\r\n" + "(⁄ ⁄•⁄ω⁄•⁄ ⁄)"
#msg ="repo number: " + str(getNews()[0]) + "\r\n" +"GitHub description: " + getNews()[1]+ "\r\n" + "Link: " + getNews()[2] + "\r\n" + "CVE Vulnerability Description: " + cve_des + "\r\n" + "(⁄ ⁄•⁄ω⁄•⁄ ⁄)"
#msg = translate(msg)
tg_token = os.getenv('TG_TOKEN')
tg_chat_id = os.getenv('TG_CHAT_ID')
bot = telegram.Bot(token=tg_token)
await bot.send_message(chat_id=tg_chat_id, text=text + "\r\n" + msg)
#Send Wechat
def Wechat(cve_des):
#The title of the message
text = r'喵~~ Senpai! 有新的CVE更新送达!'
#Process SCKEYs
sckey = os.getenv('SCKEY')
sckeys = sckey.split(",")
#The contents of the message
msg ="\n"+"* CVE相关项目总数: " + str(getNews()[0]) + "\n" +"* GitHub项目介绍: " + getNews()[1]+"\n"+"> ("+translate(getNews()[1])+")"+"\n"+ "* 链接: " + getNews()[2] + "\n" + "* 该CVE编号的详情: " + cve_des +"\n"+"> ("+translate(cve_des)+")"+"\n"+"\n"+ "(⁄ ⁄•⁄ω⁄•⁄ ⁄)"
#msg = translate(msg)
for key in sckeys:
uri = 'https://sc.ftqq.com/'+ key +'.send?text={}&desp={}'.format(text, msg)
send = requests.get(uri)
#Send Message
def sendNews(total_count):
try:
api = "https://api.github.com/search/repositories?q=CVE-2023&sort=updated"
req = requests.get(api).text
respJson = json.loads(req)
repo_name = respJson["items"][0]["name"]
if int(total_count) < getNews()[0]:
cve_id = getid(respJson)
print("[INFO] CVE ID: ", cve_id)
#Description from CVE
if exist_cve(cve_id):
cve_des = get_cve_des(cve_id)
else:
exit(0)
if int(option) == 1:
print("[INFO] CVE updates found! Sending Wechat!")
Wechat(cve_des)
elif int(option) == 2:
print("[INFO] CVE updates found! Sending TG!")
asyncio.run(TG(cve_des))
elif int(option) == 3:
print("[INFO] CVE updates found! Sending TG and Wechat!")
asyncio.run(TG(cve_des))
Wechat(cve_des)
print(getNews())
time.sleep(5)
total_count = getNews()[0]
return total_count
elif int(total_count) > getNews()[0]:
print("[WARN] Some repos are deleted!")
total_count = getNews()[0]
return total_count
else:
print("[INFO] No CVE updates found! Bye!")
exit()
except Exception as e:
raise e
if __name__ == '__main__':
total_count = os.getenv('total_count')
puturl=r'https://api.github.com/repos/'+gh_repo+r'/actions/secrets/TOTAL_COUNT'
key_id='qwq'
encrypted_value=createsecret(getpublickey(Auth,geturl),sendNews(total_count))
setsecret(encrypted_value,key_id,puturl)
#sendNews()
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2022 Nek0Suk1(KiraPGR)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# Github-CVE-Listener


```
_______ ________ _________ ___ ___ __ __ _______
/______/\ /_______/\/________/\/__/\ /__/\/_/\/_/\/_______/\
\::::__\/_\__.::._\/\__.::.__\/\::\ \\ \ \:\ \:\ \::: _ \ \
\:\ /____/\ \::\ \ \::\ \ \::\/_\ .\ \:\ \:\ \::(_) \/_
\:\\_ _\/ _\::\ \__ \::\ \ \:: ___::\ \:\ \:\ \:: _ \ \
\:\_\ \ \/__\::\__/\ \::\ \ \: \ \\::\ \:\_\:\ \::(_) \ \
\_____\/\________\/ \__\/ \__\/ \::\/\_____\/\_______\/
______ __ __ ______ __ ________ ______ _________ ______ ___ __ ______ ______
/_____/\/_/\ /_/\/_____/\ /_/\ /_______/\/_____/\/________/\/_____/\/__/\ /__/\/_____/\/_____/\
\:::__\/\:\ \\ \ \::::_\/_ \:\ \ \__.::._\/\::::_\/\__.::.__\/\::::_\/\::\_\\ \ \::::_\/\:::_ \ \
\:\ \ _\:\ \\ \ \:\/___/\ \:\ \ \::\ \ \:\/___/\ \::\ \ \:\/___/\:. `-\ \ \:\/___/\:(_) ) )_
\:\ \/_/\:\_/.:\ \::___\/_ \:\ \____ _\::\ \__\_::._\:\ \::\ \ \::___\/\:. _ \ \::___\/\: __ `\ \
\:\_\ \ \ ..::/ /\:\____/\ \:\/___/\/__\::\__/\ /____\:\ \::\ \ \:\____/\. \`-\ \ \:\____/\ \ `\ \ \
\_____\/\___/_( \_____\/ \_____\/\________\/ \_____\/ \__\/ \_____\/\__\/ \__\/\_____\/\_\/ \_\/
```
Get latest CVE EXP/POC from GitHub in WeChat!
## Tips
* The Program runs with Github Actions, no need to use your own server
* [Chinese Version](https://github.com/Kira-Pgr/Github-CVE-Listener/blob/main/README_ZH.md)
## Usage
* **preparations**
* **GitHub**
* fork my repo
Sign up or log into your GitHub account and click the "fork" button on the page

After that, a repo with the same name will show up in your account.
Follow the steps below in **your repository**
* Create a new GitHub Personal Access Token
1)Go to the New Token [Page](https://github.com/settings/tokens/new)
2)Set note to `GH_TOKEN` , select "repo",set expiration to no expiration,click `Generate token` ,and remember to **COPY AND SAVE** your token
> **Attention! Once you leave the page, you won't able to see your token any more!**

* Create a new repository secret
1. Go to Setting -> Secrets -> New repository secret,Create 6 secrets:`GH_TOKEN` `SCKEY` `TOTAL_COUNT` `OPTION` `TG_CHAT_ID` `TG_TOKEN`
> **Don't create the secrets you don't need**
2. Update the values
The value of `OPTION`: `1` for pushing to WeChat, `2` for using Telegram bot, `3` for using all of them
The value of `GH_TOKEN`: Your GitHub Personal Access Token
The value of `TOTAL_COUNT`: 0
* If you want to sent message to WeChat
The value of `SCKEY`: Your SendKey
> If you are using multiple SendKeys, please include them all in the value of the secret,separated by commas and without any line breaks or leading/trailing commas.
>
> For example:
>
> ```
> key1,key2,key3,...
> ```
* If you want to sent message to Telegram
The value of `TG_CHAT_ID`: Your ID or the group's ID
The value of `TG_TOKEN`: The bot's token
> **No spaces or line breaks is allowed at either the start or the end**

* **WeChat ”Server-Chan“**
* [Log in](https://sct.ftqq.com/login)
> Notice: If the QR Code doesn't load, try to open the image in a new tab
> 
* Copy your [SendKey](https://sct.ftqq.com/sendkey) for later use

* **Telegram Bot**
* [Get Your ID](https://telegram.me/myidbot)
* [Get Your Token](https://telegram.me/BotFather)
* **Run the program**
* Go to the Action Tab,Click the green button(I understand my workflow...) in the middle

* After refreshing the page,you'll see a workflow called `CVE-Monitor`.
* Select the `CVE-Monitor` workflow,You'll see a notice(this schedule was disabled......)

* Press `enable workflow` button
> (If you didn't experience the problem, just ignore what I've just said = = )
* Click star twice to start the workflow
* Go to Action tab -> `CVE-Monitor` workflow -> `build` -> `Monitor CVE` You'll see the logs of each workflow run, just check if there're any errors
* Normally, you'll receive a message now
* Last,if the program functioned correctly, secret `TOTAL_COUNT` should be updated
## Other info
* The workflow is currently configured to run every 10 minutes,if you want to change that,go to [AutoRun.yml](https://github.com/Kira-Pgr/Github-CVE-Listener/blob/main/.github/workflows/AutoRun.yml), be sure to read the [GitHub Docs](https://docs.github.com/en/actions/reference/events-that-trigger-workflows#scheduled-events).
> **Attention! Actions schedules run at most every 5 minutes.**
* Tip: GitHub will tell you the meaning of the schedule expression while you are changing it

ref:
*https://github.com/kiang70/Github-Monitor/*
*https://github.com/Hostage-02/AutoApi*
## Star History
[](https://star-history.com/#Kira-Pgr/Github-CVE-Listener&Date)
================================================
FILE: README_ZH.md
================================================
# Github-CVE-Listener
推送GitHub最新CVE EXP/POC到微信或者TG

## 说明
* 使用Github Actions运行,无需拥有服务器
* 懒得自己搭的可以加入[TG频道](https://t.me/nanosec47)
* [英文版README](https://github.com/Kira-Pgr/Github-CVE-Listener/blob/main/README.md)
## 使用步骤
* **准备**
* **GitHub方面的准备**
* fork本项目
登陆/新建github账号,回到本项目页面,点击右上角fork本项目的代码,

然后你账号下会出现一个一模一样的项目,接下来的操作均在你的这个项目下进行。
* 新建github密钥
1)进入创建新Token[页面](https://github.com/settings/tokens/new)
2)设置名字为 `GH_TOKEN` , 然后勾选repo,过期时间选择永不过期,点击 `Generate token` ,最后**复制保存**生成的github密钥
> **注意!一旦离开页面下次就看不到了!**

* 新建secret
1. 依次点击页面上栏右边的 Setting -> 左栏 Secrets -> 右上 New repository secret,新建6个secret:`GH_TOKEN` `SCKEY` `TOTAL_COUNT` `OPTION` `TG_CHAT_ID` `TG_TOKEN`
> ** 注意:不需要用到的Secret项值可以不建 **
2. 填写每个Secret的值
`OPTION`填写1或2或3(1表示微信推送,2表示TG Bot推送, 3表示都推送--以满足一些特殊情况)
`GH_TOKEN`填写你获得的GitHub密钥
`TOTAL_COUNT`填0
* 如推送微信
`SCKEY`填写你的SendKey(获取方式见下文)
> 如果你同时使用多个SendKey,请把它们都写在这个Secret的值中(用逗号间隔,不需要换行,开头和最后也不要加逗号)
>
> 像这样`key1,key2,key3,...`
* 如推送TG Bot
`TG_CHAT_ID`填你或者你所在群的ID
`TG_CHAT_ID`填你Bot的Token(获取方式均见下文)
> **注意!填入内容注意前后不要有空格空行**

* **微信Server酱**
* [登陆Server酱](https://sct.ftqq.com/login)
> PS:如果进入登陆界面后二维码无法显示,把二维码图片在新标签页打开即可
> 
* 复制你的[SendKey](https://sct.ftqq.com/sendkey)备用

* **TG Bot方面**
* [获取ID](https://telegram.me/myidbot)
* [获取Token](https://telegram.me/BotFather)
* **运行**
* 点击上栏中间的Action进入运行日志页面,中间应该有个绿色按钮(I understand my workflow...),点击。

* 自动刷新后,会看到左边有一个叫`CVE-Monitor`的流程
* 点进去,然后会看到有个黄条(this schedule was disabled......)

* 点击 enable workflow 按钮
> (并不是很确定是否都需要进行以上4个步骤,如果你没有出现这种情况,直接忽略掉好啦 = = )
* 点击两次右上角的星星(star,在fork按钮的旁边)启动action
* 再点击上面的Action选择`CVE-Monitor`流程 -> `build` -> `Monitor CVE` 就能看到每次的运行日志,看看有没有报错
* 没有报错的话微信里应该就会有推送了
* 最后,再检查一下Secrets页面,应该能看到`TOTAL_COUNT`那一栏显示刚刚更新了
## 补充
* 程序默认是每10分钟监测一下GitHub上有没有和CVE相关的repo更新,如果你想修改,可以在[AutoRun.yml](https://github.com/Kira-Pgr/Github-CVE-Listener/blob/main/.github/workflows/AutoRun.yml)中依照[文档](https://docs.github.com/en/actions/reference/events-that-trigger-workflows#scheduled-events)修改
> **注意! 两次监测间隔时间不得小于5分钟**
* Tip: 在修改时,贴心的GitHub会提示间隔的时间

* 如果遇到什么问题或者有什么建议,欢迎在Issues中提出
参考:
*https://github.com/kiang70/Github-Monitor/*
*https://github.com/Hostage-02/AutoApi*
gitextract_nb9paz5w/ ├── .github/ │ └── workflows/ │ └── AutoRun.yml ├── Github-CVE-Listener.py ├── LICENSE ├── README.md └── README_ZH.md
SYMBOL INDEX (11 symbols across 1 files) FILE: Github-CVE-Listener.py function translate (line 25) | def translate(text): function getpublickey (line 38) | def getpublickey(Auth,geturl): function createsecret (line 52) | def createsecret(public_key,secret_value): function setsecret (line 59) | def setsecret(encrypted_value,key_id,puturl): function getNews (line 69) | def getNews(): function exist_cve (line 92) | def exist_cve(cve): function get_cve_des (line 104) | def get_cve_des(cve): function getid (line 123) | def getid(respJson): function TG (line 145) | async def TG(cve_des): function Wechat (line 155) | def Wechat(cve_des): function sendNews (line 168) | def sendNews(total_count):
Condensed preview — 5 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (25K chars).
[
{
"path": ".github/workflows/AutoRun.yml",
"chars": 1193,
"preview": "# This workflow will install Python dependencies, run tests and lint with a single version of Python\n# For more informat"
},
{
"path": "Github-CVE-Listener.py",
"chars": 8804,
"preview": "#coding = utf-8\n\nimport urllib\nimport requests,re,time\nimport html\nimport json\nimport os\nfrom base64 import b64encode\nfr"
},
{
"path": "LICENSE",
"chars": 1074,
"preview": "MIT License\n\nCopyright (c) 2022 Nek0Suk1(KiraPGR)\n\nPermission is hereby granted, free of charge, to any person obtaining"
},
{
"path": "README.md",
"chars": 6618,
"preview": "# Github-CVE-Listener\n\n\n. The extraction includes 5 files (21.5 KB), approximately 7.0k tokens, and a symbol index with 11 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.