91def scan_text(text: str) -> tuple[EgressFinding, ...]:
92 """Return content-oriented findings without returning matched content."""
93 if not isinstance(text, str):
94 raise TypeError(
"outbound content must be text")
95 findings: list[EgressFinding] = []
97 (
"github-token-shape", _GITHUB_SHAPE),
98 (
"aws-key-shape", _AWS_SHAPE),
99 (
"openai-key-shape", _OPENAI_SHAPE),
100 (
"telegram-token-shape", _TELEGRAM_SHAPE),
103 EgressFinding(kind=kind, start=match.start(), end=match.end())
104 for match
in shape.finditer(text)
108 kind=
"named-sensitive-value",
109 start=match.start(1),
112 for match
in _NAMED_VALUE_SHAPE.finditer(text)
115 covered = {(finding.start, finding.end)
for finding
in findings}
116 for match
in _TOKEN_SHAPE.finditer(text):
117 span = (match.start(), match.end())
118 if span
in covered
or any(
119 start <= span[0]
and span[1] <= end
for start, end
in covered
122 candidate = match.group(0)
123 if len(candidate) < _MIN_ENTROPY_LENGTH:
126 if entropy >= _ENTROPY_THRESHOLD:
129 kind=
"high-entropy-token",
137 (finding.kind, finding.start, finding.end): finding
for finding
in findings
139 result = tuple(unique[key]
for key
in sorted(unique))
143 f
"scanned outbound text length={len(text)} findings={len(result)}",