Ordered by severity, then signals introduced in this release. Hidden characters are shown as ⟨U+…⟩.
-
file mixes tab and space indentation (3 tab-indented and 3123 space-indented lines) (raw pass, confidence 0.40)
from fontTools.misc.textTools import (
bytechr,
byteord,
bytesjoin,
-
identifier `α` contains homoglyph candidates: α (03B1)→a (in string/comment) (raw pass, confidence 0.35)
_UNIT_VECTOR_THRESHOLD = cos(3 / 8 * pi)
-
identifier `α` contains homoglyph candidates: α (03B1)→a (in string/comment) (raw pass, confidence 0.35)
_UNIT_VECTOR_THRESHOLD = cos(3 / 8 * pi)
-
identifier `α` contains homoglyph candidates: α (03B1)→a (in string/comment) (raw pass, confidence 0.35)
_UNIT_VECTOR_THRESHOLD = cos(3 / 8 * pi)
-
reach-by-name through `globals` (ast pass, confidence 0.60)
def wrapper(function, setup_func):
function = globals()[function]
setup_func = globals()[setup_func]
likely benign
LLM, confidence 0.90
Benchmark decorator resolves a function and setup function by name from module globals.
Reasoning
globals() lookup of a benchmark function by name inside a timing decorator, a common pattern for resolving names passed as strings to the benchmark wrapper. Nothing decodes, spawns or reaches the network.
-
reach-by-name through `globals` (ast pass, confidence 0.60)
function = globals()[function]
setup_func = globals()[setup_func]
def wrapped():
likely benign
LLM, confidence 0.90
Second globals() name lookup in the same benchmark wrapper.
Reasoning
Same globals() name lookup in the benchmark wrapper; it only times a local conversion routine.
-
`__import__` called on a non-literal expression (ast pass, confidence 0.70)
try:
imports = __import__(pkg, globals(), locals(), ["main"])
except ImportError as e:
continue
likely benign
LLM, confidence 0.80
help() imports fontTools submodules by name to print their docstrings.
Reasoning
Loop imports known fontTools submodules to collect their help text, with ImportError swallowed. The package names are internal, so the dynamic import is a standard plugin or help-discovery idiom, not a payload loader.
-
reach-by-name through `globals` (ast pass, confidence 0.60)
for name in ("double", "complex", "int"):
globals()[name] = None
for name in ("cfunc", "inline"):
likely benign
LLM, confidence 0.90
Cython fallback stubs out type names in module globals.
Reasoning
Compatibility shim that sets placeholder names in globals when Cython is unavailable, a standard fallback so pure-Python mode works.
-
reach-by-name through `globals` (ast pass, confidence 0.60)
for name in ("cfunc", "inline"):
globals()[name] = _empty_decorator
locals = lambda **_: _empty_decorator
likely benign
LLM, confidence 0.90
Cython fallback installs no-op decorators into module globals.
Reasoning
Same Cython fallback: decorator names are assigned to no-op stand-ins in globals when Cython is absent.
-
reach-by-name through `locals.get` (ast pass, confidence 0.60)
for arg in ("msg", "level"):
if locals().get(arg) is not None:
raise ValueError("'%s' can't be specified without a 'logger'" % arg)
self.logger = logger
likely benign
LLM, confidence 0.90
Checks local arguments to reject msg/level when a logger is supplied.
Reasoning
locals() is read to check whether msg or level were passed alongside a logger argument, a plain argument-validation check.
-
file mixes tab and space indentation (19 tab-indented and 178 space-indented lines) (raw pass, confidence 0.40)
class ResourceError(Exception):
pass
-
file mixes tab and space indentation (9 tab-indented and 320 space-indented lines) (raw pass, confidence 0.40)
from .psOperators import (
PSOperators,
ps_StandardEncoding,
ps_array,
-
file mixes tab and space indentation (13 tab-indented and 129 space-indented lines) (raw pass, confidence 0.40)
pack(fmt, object):
'object' is either a dictionary or an instance (or actually
anything that has a __dict__ attribute). If it is a dictionary,
its keys are used for names. If it is an instance, it's
-
file mixes tab and space indentation (40 tab-indented and 113 space-indented lines) (raw pass, confidence 0.40)
for i in range(1, n + 1):
last = BinomialCoefficient[-1]
this = tuple(last[j - 1] + last[j] for j in range(len(last))) + (0,)
BinomialCoefficient.append(this)
-
`eval` called on a non-literal expression (ast pass, confidence 0.70)
penName = sys.argv[1]
funcs = [(name, eval(f)) for name, f in zip(sys.argv[2::2], sys.argv[3::2])]
printGreenPen(penName, funcs, file=sys.stdout)
likely benign
LLM, confidence 0.70
Developer CLI evals user-supplied Python expressions from argv to build pen functions.
Reasoning
eval on command-line arguments in a developer script that prints glyph pen output. The user supplies the expressions to their own process, so it is an unsafe-looking but unremarkable dev-tool pattern, not hidden malicious execution.
-
reach-by-name through `globals` (ast pass, confidence 0.60)
def wrapper(function, setup_func):
function = globals()[function]
setup_func = globals()[setup_func]
likely benign
LLM, confidence 0.90
Benchmark decorator resolves functions by name from module globals.
Reasoning
Same benchmark-decorator globals() name resolution as the cu2qu benchmark.
-
reach-by-name through `globals` (ast pass, confidence 0.60)
function = globals()[function]
setup_func = globals()[setup_func]
def wrapped():
likely benign
LLM, confidence 0.90
Second globals() name lookup in the qu2cu benchmark wrapper.
Reasoning
Same globals() lookup in the benchmark wrapper, used only for timing.
-
file mixes tab and space indentation (8 tab-indented and 116 space-indented lines) (raw pass, confidence 0.40)
def main(args=None):
-
file mixes tab and space indentation (43 tab-indented and 518 space-indented lines) (raw pass, confidence 0.40)
class SFNTReader(object):
def __new__(cls, *args, **kwargs):
-
file imports decoder module(s) zlib and calls `.decompress()` — embedded payload decompressed at runtime (ast pass, confidence 0.75)
)
data = zlib.decompress(rawData)
if len(data) != self.origLength:
raise TTLibError(
likely benign
LLM, confidence 0.90
Decompresses a zlib-compressed WOFF table during font loading.
Reasoning
zlib.decompress of a WOFF table's raw data, checked against the declared origLength. This is the standard WOFF format decoding path, not a hidden payload.
-
reach-by-name through `vars` (ast pass, confidence 0.60)
if name in metricNames:
vars(self)[name] = safeEval(attrs["value"])
else:
log.warning(
likely benign
LLM, confidence 0.85
XML fromXML sets a whitelisted metric attribute via vars(self) using safeEval.
Reasoning
Sets an XML-parsed attribute on the object after filtering against a fixed list of metric names, with values passed through safeEval, the restricted literal evaluator. This is ordinary table deserialization.
-
file mixes tab and space indentation (12 tab-indented and 104 space-indented lines) (raw pass, confidence 0.40)
if TYPE_CHECKING:
from fontTools.misc.xmlWriter import XMLWriter
from fontTools.ttLib import TTFont
-
file mixes tab and space indentation (6 tab-indented and 642 space-indented lines) (raw pass, confidence 0.40)
from fontTools.misc.textTools import (
bytechr,
byteord,
bytesjoin,
-
reach-by-name through `vars` (ast pass, confidence 0.60)
if name in componentNames:
vars(self)[name] = safeEval(attrs["value"])
else:
log.warning("unknown name '%s' being ignored by EbdtComponent.", name)
likely benign
LLM, confidence 0.85
EBDT component XML parsing sets whitelisted attributes via vars(self) with safeEval.
Reasoning
Same whitelisted-name attribute assignment with safeEval for EBDT component XML parsing.
-
file mixes tab and space indentation (28 tab-indented and 544 space-indented lines) (raw pass, confidence 0.40)
from .BitmapGlyphMetrics import (
BigGlyphMetrics,
bigGlyphMetricsFormat,
SmallGlyphMetrics,
-
reach-by-name through `vars` (ast pass, confidence 0.60)
metricObj = SbitLineMetrics()
vars(curTable)[metric] = metricObj
dummy = sstruct.unpack2(
sbitLineMetricsFormat, data[i : i + 12], metricObj
likely benign
LLM, confidence 0.90
EBLC table stores a sbit line metrics object on itself via vars() during binary decoding.
Reasoning
Stores a metric object on the table under a fixed metric name and then unpacks binary data into it using sstruct, standard binary table handling.
-
reach-by-name through `vars` (ast pass, confidence 0.60)
for metric in ("hori", "vert"):
metricObj = vars(curTable)[metric]
data = sstruct.pack(sbitLineMetricsFormat, metricObj)
dataList.append(data)
likely benign
LLM, confidence 0.90
EBLC serialization reads hori/vert metric objects via vars() to pack them.
Reasoning
Reads fixed hori/vert metric attributes to pack them back to binary, the serialization counterpart of the code above.
-
reach-by-name through `vars` (ast pass, confidence 0.60)
metricObj.fromXML(name, attrs, content, ttFont)
vars(self)[direction] = metricObj
elif name in dataNames:
vars(self)[name] = safeEval(attrs["value"])
likely benign
LLM, confidence 0.85
EBLC XML parser stores direction metrics and whitelisted data values via vars().
Reasoning
XML parsing assigns the direction-specific metric object or a whitelisted data name with safeEval, consistent with the other table modules.
-
reach-by-name through `vars` (ast pass, confidence 0.60)
elif name in dataNames:
vars(self)[name] = safeEval(attrs["value"])
else:
log.warning("unknown name '%s' being ignored in BitmapSizeTable.", name)
likely benign
LLM, confidence 0.85
Sets a whitelisted BitmapSizeTable attribute from parsed XML via vars(self).
Reasoning
The name is checked against a fixed whitelist (dataNames) before the vars(self) assignment, and the value goes through safeEval. This is a reflective setter over known XML attributes, not a hidden channel.
-
reach-by-name through `vars` (ast pass, confidence 0.60)
if name in metricNames:
vars(self)[name] = safeEval(attrs["value"])
likely benign
LLM, confidence 0.85
Sets a whitelisted metric attribute from XML via vars(self).
Reasoning
Same pattern as the sibling finding: the name is guarded by membership in metricNames and the value passes through safeEval. Ordinary XML deserialization for font metrics.
-
file mixes tab and space indentation (5 tab-indented and 31 space-indented lines) (raw pass, confidence 0.40)
FFTMFormat = """
> # big endian
version: I
FFTimeStamp: Q
-
file mixes tab and space indentation (50 tab-indented and 602 space-indented lines) (raw pass, confidence 0.40)
panoseFormat = """
bFamilyType: B
bSerifStyle: B
bWeight: B
-
file mixes tab and space indentation (9 tab-indented and 159 space-indented lines) (raw pass, confidence 0.40)
<SVG>
<svgDoc endGlyphID="1" startGlyphID="1">
<![CDATA[ <complete SVG doc> ]]
-
file mixes tab and space indentation (17 tab-indented and 202 space-indented lines) (raw pass, confidence 0.40)
VDMX_HeaderFmt = """
> # big endian
version: H # Version number (0 or 1)
numRecs: H # Number of VDMX groups present
-
file mixes tab and space indentation (6 tab-indented and 2012 space-indented lines) (raw pass, confidence 0.40)
from fontTools.misc.fixedTools import (
fixedToFloat as fi2fl,
floatToFixed as fl2fi,
floatToFixedToStr as fl2str,
-
file mixes tab and space indentation (9 tab-indented and 275 space-indented lines) (raw pass, confidence 0.40)
GVAR_HEADER_FORMAT_HEAD = """
> # big endian
version: H
reserved: H
-
file mixes tab and space indentation (4 tab-indented and 98 space-indented lines) (raw pass, confidence 0.40)
hdmxHeaderFormat = """
> # big endian!
version: H
numRecords: H
-
file mixes tab and space indentation (18 tab-indented and 86 space-indented lines) (raw pass, confidence 0.40)
from fontTools.misc.timeTools import (
timestampFromString,
timestampToString,
timestampNow,
-
file mixes tab and space indentation (18 tab-indented and 98 space-indented lines) (raw pass, confidence 0.40)
from fontTools.misc.fixedTools import (
ensureVersionIsLong as fi2ve,
versionToFixed as ve2fi,
)
-
file mixes tab and space indentation (17 tab-indented and 109 space-indented lines) (raw pass, confidence 0.40)
maxpFormat_0_5 = """
> # big endian
tableVersion: i
numGlyphs: H
-
file mixes tab and space indentation (7 tab-indented and 1071 space-indented lines) (raw pass, confidence 0.40)
from fontTools.misc.textTools import (
bytechr,
byteord,
bytesjoin,
-
file mixes tab and space indentation (10 tab-indented and 259 space-indented lines) (raw pass, confidence 0.40)
postFormat = """
>
formatType: 16.16F
italicAngle: 16.16F # italic angle in degrees
-
file mixes tab and space indentation (13 tab-indented and 79 space-indented lines) (raw pass, confidence 0.40)
sbixHeaderFormat = """
>
version: H # Version number (set to 1)
flags: H # The only two bits used in the flags field are bits 0
-
file mixes tab and space indentation (14 tab-indented and 231 space-indented lines) (raw pass, confidence 0.40)
from fontTools.misc.fixedTools import (
fixedToFloat as fi2fl,
floatToFixed as fl2fi,
floatToFixedToStr as fl2str,
-
file mixes tab and space indentation (18 tab-indented and 92 space-indented lines) (raw pass, confidence 0.40)
from fontTools.misc.fixedTools import (
ensureVersionIsLong as fi2ve,
versionToFixed as ve2fi,
)
-
`eval` called on a non-literal expression (ast pass, confidence 0.70)
else:
if conv.aux and not eval(conv.aux, None, self.__dict__):
continue
if hasattr(self, conv.name):
likely benign
LLM, confidence 0.85
Evaluates a conditional expression from OpenType converter metadata during table decompile.
Reasoning
The eval evaluates conv.aux, a condition expression from fontTools' own OpenType table definitions, not attacker-supplied text. This is the library's documented mechanism for conditional fields.
-
`eval` called on a non-literal expression (ast pass, confidence 0.70)
else:
if conv.aux and not eval(conv.aux, None, table):
continue
table[conv.name] = conv.read(reader, font, table)
likely benign
LLM, confidence 0.85
Evaluates a conditional field expression from internal OpenType spec during reading.
Reasoning
eval of conv.aux comes from the library's internal table spec, so the input is trusted code-generated metadata. Same legitimate conditional-field mechanism.
-
`eval` called on a non-literal expression (ast pass, confidence 0.70)
else:
if conv.aux and not eval(conv.aux, None, table):
continue
try:
likely benign
LLM, confidence 0.85
Evaluates a conditional field expression from the internal OpenType spec during table handling.
Reasoning
eval of conv.aux from the static OpenType spec, used to decide whether to skip a field. Standard fontTools behavior.
-
`eval` called on a non-literal expression (ast pass, confidence 0.70)
else:
if conv.aux and not eval(conv.aux, None, vars(self)):
continue
value = getattr(
likely benign
LLM, confidence 0.85
Evaluates a spec-defined condition over table attributes during table compilation.
Reasoning
eval of the static spec's aux expression over the table's own vars, to gate field processing. No external input reaches the expression.
-
`eval` called on a non-literal expression (ast pass, confidence 0.70)
else:
converterClass = eval(spec.type, tableNamespace, converterMapping)
conv = converterClass(
likely benign
LLM, confidence 0.85
Resolves a converter class by evaluating a spec type name against a fixed namespace.
Reasoning
eval resolves a converter class name from spec.type inside a fixed namespace and mapping. The inputs come from fontTools' bundled table definitions, so this is a class lookup, not code injection.
-
`compile` called on a non-literal expression (ast pass, confidence 0.70)
if self.aux and not self.repeat:
self.aux = compile(self.aux, "<string>", "eval")
self.tableClass = tableClass
self.isCount = name.endswith("Count") or name in [
likely benign
LLM, confidence 0.85
Compiles a spec-defined condition expression once at converter construction.
Reasoning
compile of self.aux in eval mode turns a spec-defined condition into a code object, with the source coming from the library's own table definitions. No runtime attacker input is involved.
-
`eval` called on a non-literal expression (ast pass, confidence 0.70)
else:
if conv.aux and not eval(conv.aux, None, vars(self)):
continue
value = getattr(
likely benign
LLM, confidence 0.85
Evaluates a spec-defined conditional expression over table attributes.
Reasoning
Same spec-driven eval of conv.aux over vars(self) as the otBase findings, part of the normal OpenType decompile/compile flow.
-
file mixes tab and space indentation (10 tab-indented and 114 space-indented lines) (raw pass, confidence 0.40)
sbixGlyphHeaderFormat = """
>
originOffsetX: h # The x-value of the point in the glyph relative to its
# lower-left corner which corresponds to the origin of
-
file mixes tab and space indentation (8 tab-indented and 137 space-indented lines) (raw pass, confidence 0.40)
sbixStrikeHeaderFormat = """
>
ppem: H # The PPEM for which this strike was designed (e.g., 9,
# 12, 24)
-
6 rows of escape runs, lines 582-582 (first: 32 consecutive `\NNN` octal escapes (entropy 5.0 bits/byte)) (raw pass, confidence 0.65)
bc = b"""@;:9876543210/.-,+*)(\'&%$#"! \037\036\035\034\033\032\031\030\027\026\025\024\023\022\021\020\017\016\015\014\013\012\011\010\007\006\005\004\003\002\001\000,\001\260\030CXEj\260\031C`\260F#D#\020 \260FN\360M/\260\000\022\033!#\0213Y-,\001\260\030CX\260\005+\260\000\023K\260\024PX\261\000@8Y\260\006+\033!
likely benign
LLM, confidence 0.80
A bytes literal holding a TrueType bytecode program written with octal escapes.
Reasoning
The raw pass flags a long bytes literal of octal escapes. That is the expected form of a TrueType bytecode program (the instruction stream of a fixed built-in table), which contains many small byte values. Raw-pass findings have a high false-positive rate and this is a known data constant, not an encoded payload.
-
reach-by-name through `locals.get` (ast pass, confidence 0.60)
for name in ("verbose", "quiet"):
val = locals().get(name)
if val is not None:
deprecateArgument(name, "configure logging instead")
likely benign
LLM, confidence 0.90
Reads deprecated verbose/quiet arguments from locals to warn users.
Reasoning
locals().get reads the names 'verbose' and 'quiet' from the function's own arguments to emit a deprecation warning. It is a fixed, local lookup with no dynamic execution.
-
`__import__` called on a non-literal expression (ast pass, confidence 0.90)
try:
__import__("fontTools.ttLib.tables." + pyTag)
except ImportError as err:
likely benign
LLM, confidence 0.80
Dynamically imports the fontTools table module matching a font's table tag.
Reasoning
The import is built from a fixed 'fontTools.ttLib.tables.' prefix plus pyTag, which is derived from a font table tag and converted to a Python identifier. Only modules inside fontTools' own tables package can be loaded, and ImportError is caught for unknown tags. That is the standard dynamic table-loader pattern, though the severity is high because the tag comes from untrusted font data.
-
file mixes tab and space indentation (36 tab-indented and 1383 space-indented lines) (raw pass, confidence 0.40)
from fontTools.ttLib import (
TTFont,
TTLibError,
getTableModule,
-
file mixes tab and space indentation (12 tab-indented and 501 space-indented lines) (raw pass, confidence 0.40)
from fontTools.cffLib import (
maxStackLimit,
TopDictIndex,
buildOrder,
Run disclude locally to verify. These commands scan the published file; the "new in this release" marks come from comparing it with the previous release's file, which they don't repeat. Add --format sarif for SARIF output. Add --llm (with an API key in the environment) to include the LLM review.