过滤 AWS 资源访问验证成功通知
This commit is contained in:
@@ -34,6 +34,15 @@ WARNING_TERMS = re.compile(
|
||||
EXPLICIT_CLOSURE_SUBJECT = re.compile(
|
||||
r"permanent closure confirmation|永久关闭确认", re.I
|
||||
)
|
||||
ACCESS_VALIDATED = re.compile(
|
||||
r"your\s+request\s+for\s+accessing\s+AWS\s+resources\s+has\s+been\s+"
|
||||
r"(?:successfully\s+)?validated\b|"
|
||||
r"您访问\s*AWS\s*资源的请求已(?:得到验证|通过验证|验证成功)", re.I
|
||||
)
|
||||
RISK_ALERT_SUBJECT = re.compile(
|
||||
r"suspicious activity|security (?:alert|warning)|abuse report|phishing|compromis|"
|
||||
r"可疑活动|异常活动|滥用|钓鱼|泄露|安全警告", re.I
|
||||
)
|
||||
SECRET = re.compile(
|
||||
r"\b(?:AKIA|ASIA)[A-Z0-9]{16}\b|"
|
||||
r"\bBearer\s+[A-Za-z0-9._~+/-]+|"
|
||||
@@ -76,6 +85,15 @@ DOCUMENT_REQUEST = re.compile(
|
||||
r"(?:请|需要|必须).{0,30}(?:上传|提交|提供).{0,40}(?:材料|证件|身份证|护照|账单|证明)", re.I
|
||||
)
|
||||
RISK_EVIDENCE = re.compile(ACCOUNT_RISK.pattern + "|" + DOCUMENT_REQUEST.pattern, re.I)
|
||||
RESOURCE_RISK_ACTION = re.compile(
|
||||
r"(?:please|must|required to|take action).{0,80}(?:remove|delete|stop|disable|revoke|rotate)"
|
||||
r".{0,100}(?:phishing|abus(?:e|ive)|malicious|compromised|unauthorized)|"
|
||||
r"(?:请|必须|需要|立即).{0,40}(?:删除|移除|停止|停用|撤销|轮换|更换)"
|
||||
r".{0,60}(?:钓鱼|滥用|恶意|泄露|未授权)", re.I
|
||||
)
|
||||
ACCESS_NOTICE_RISK_EVIDENCE = re.compile(
|
||||
RISK_EVIDENCE.pattern + "|" + RESOURCE_RISK_ACTION.pattern, re.I
|
||||
)
|
||||
CONDITIONAL = re.compile(r"\bif\b|如果|假如|倘若|若|如(?:您|你)", re.I)
|
||||
NON_RESPONSE = re.compile(
|
||||
r"\b(?:do not|don't|fail to|failed to|unless)\b|"
|
||||
@@ -84,7 +102,7 @@ NON_RESPONSE = re.compile(
|
||||
)
|
||||
|
||||
|
||||
def has_explicit_risk(text):
|
||||
def has_explicit_risk(text, evidence=RISK_EVIDENCE):
|
||||
# Evaluate each clause, so a conditional security tip cannot hide an actual
|
||||
# restriction elsewhere in the same paragraph (or make a code into an alert).
|
||||
for sentence in re.split(r"[\n.!?。!?;;]+|\b(?:but|however)\b|但是|然而", text, flags=re.I):
|
||||
@@ -94,11 +112,12 @@ def has_explicit_risk(text):
|
||||
for clause in re.split(r"[,,]+", sentence):
|
||||
if CONDITIONAL.search(clause):
|
||||
conditional_help = not bool(NON_RESPONSE.search(clause))
|
||||
for match in RISK_EVIDENCE.finditer(clause):
|
||||
for match in evidence.finditer(clause):
|
||||
prefix = clause[:match.start()]
|
||||
if CONDITIONAL.search(prefix) and not NON_RESPONSE.search(prefix):
|
||||
continue
|
||||
if conditional_help and DOCUMENT_REQUEST.match(match.group()):
|
||||
if conditional_help and (DOCUMENT_REQUEST.match(match.group())
|
||||
or RESOURCE_RISK_ACTION.match(match.group())):
|
||||
continue
|
||||
return True
|
||||
return False
|
||||
@@ -114,6 +133,17 @@ def is_verification_code(subject, body):
|
||||
)
|
||||
|
||||
|
||||
def is_access_validated_notice(subject, body):
|
||||
"""Ignore completed resource-access verification, while keeping risk notices."""
|
||||
combined = subject + "\n" + body
|
||||
return bool(
|
||||
ACCESS_VALIDATED.search(combined)
|
||||
and not (has_explicit_risk(combined, ACCESS_NOTICE_RISK_EVIDENCE)
|
||||
or EXPLICIT_CLOSURE_SUBJECT.search(subject)
|
||||
or RISK_ALERT_SUBJECT.search(subject))
|
||||
)
|
||||
|
||||
|
||||
class PlainHTML(HTMLParser):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
@@ -238,7 +268,7 @@ def extract(message, received):
|
||||
subject = header_value(message, "Subject")
|
||||
body = body_text(message)
|
||||
combined = subject + "\n" + body
|
||||
if is_verification_code(subject, body):
|
||||
if is_verification_code(subject, body) or is_access_validated_notice(subject, body):
|
||||
return None
|
||||
if not RISK_TERMS.search(combined) or not (
|
||||
WARNING_TERMS.search(combined) or EXPLICIT_CLOSURE_SUBJECT.search(subject)
|
||||
|
||||
Reference in New Issue
Block a user