fonttools 4.66.1
- Source
- https://github.com/fonttools/fonttools
- Tag scanned
4.66.1- Compared with
4.66.0(0 signals introduced since)- Files
- 820 scanned, 1813 skipped (binary, oversized, or unrecognised)
- Signals
- 0 critical · 0 warn · 80 info
- Scan time
- 31.5 s
- LLM review
- Reviewed by claude-haiku-5-5 (Anthropic): 36 of 36 warn and critical signals; 36 demoted to info.
- Disclude version
- 4.0.0
- Scanned (UTC)
- 2026-10-14 18:39
Signals
Ordered by severity, then signals introduced in this release. Hidden characters are shown as ⟨U+…⟩.
-
-
# The unit vector's X and Y components are respectively # U = (cos(α), sin(α)) # where α is the angle between the unit vector and the positive x axis. = # == sin(1/8 * pi) == 0.38268343236508984 -
# The unit vector's X and Y components are respectively # U = (cos(α), sin(α)) # where α is the angle between the unit vector and the positive x axis. = # == sin(1/8 * pi) == 0.38268343236508984 -
# U = (cos(α), sin(α)) # where α is the angle between the unit vector and the positive x axis. = # == sin(1/8 * pi) == 0.38268343236508984 -
= =likely benign Benchmark wrapper resolves function names through globals() to time them.Reasoning
The wrapper looks up a benchmark function and its setup function by name in module globals. This is a standard way to pick functions for a timing harness from command-line or configuration names, and the names come from the benchmark's own code.
-
= =likely benign Second globals() name lookup in the same benchmark wrapper.Reasoning
Same pattern as the adjacent finding: the inner wrapper resolves the setup and benchmark functions by name in module globals within a benchmarking helper. No external or untrusted input is involved.
-
= continuelikely benign help.py dynamically imports fontTools submodules by name to collect their main() entry points.Reasoning
__import__ is called with a loop variable pkg. In fontTools' help module this iterates over a fixed set of fontTools submodule names to print their help, so the import target is internal and bounded. The critical severity overstates a benign dynamic import.
-
= Nonelikely benign Cython compatibility shim that stubs out Cython type names in module globals.Reasoning
This is a fallback shim: when Cython is unavailable, it sets the names double, complex, int and similar to None in globals so that annotated pure-Python code still runs. The pattern is a known compatibility technique and is fully visible in the snippet.
-
= =likely benign Cython fallback binds cfunc and inline to a no-op decorator via globals().Reasoning
Continuation of the same no-op Cython fallback: decorator names such as cfunc and inline are bound to an empty decorator when Cython is missing. This is legitimate compatibility code.
-
=likely benign Argument-validation check reads local variables via locals().get.Reasoning
locals().get is used only to check whether the msg or level arguments were supplied, in order to raise a ValueError. This is ordinary argument validation and has no effect beyond reading local variables.
-
pass -
-
: is or . is , -
= = + -
= =likely benign Command-line helper evals user-supplied expression strings to construct symbolic pen functions.Reasoning
eval is applied to command-line arguments to build pen functions for symbolic font output. The input is supplied by the local user running the script, not fetched from a remote or hidden source, so it is a risky but expected debugging-tool design. The eval is a real code-execution path, so it is not dismissed outright.
-
= =likely benign Benchmark wrapper resolves function names through globals().Reasoning
Same benchmark-harness name lookup through globals() as in the cu2qu benchmark, with no external input or obfuscation.
-
= =likely benign Second globals() name lookup in the qu2cu benchmark wrapper.Reasoning
Second globals() name lookup in the qu2cu benchmark wrapper, matching the benign benchmarking pattern.
-
"""Open/save fonts with TTFont() or TTCollection() ./fonttools ttLib [-oFILE] [-yNUMBER] files... -
"""Return an instance of the SFNTReader sub-class which is compatible with the input file type. -
) =likely benign Decompresses a zlib-compressed WOFF table during font parsing.Reasoning
zlib.decompress is used on WOFF table data, which is compressed by specification. The result is checked against origLength. This is the expected decoding of a standard font container format, not a hidden payload.
-
=likely benign XML importer stores whitelisted metric attributes via vars(self) after safeEval.Reasoning
During XML import, the attribute value is parsed with safeEval and stored in vars(self) under a name first checked against a fixed metricNames set. The safe-eval and whitelist make this a normal deserialization path.
-
-
-
=likely benign XML importer sets whitelisted component attributes via vars(self) after safeEval.Reasoning
Same XML-import pattern: the name is checked against componentNames and the value goes through safeEval before being set on the object. This is standard table deserialization.
-
-
= = =likely benign Table loader assigns parsed line-metric objects to attributes via vars(curTable).Reasoning
The metric name is part of a known set, and the object is built from the SbitLineMetrics format and sstruct unpacking. Assigning through vars(curTable) is ordinary structured-table handling with no network or shell activity.
-
= =likely benign Reads the 'hori' and 'vert' metric attributes of a bitmap table object by name for packing.Reasoning
vars(curTable)[metric] reads a fixed attribute name from a hardcoded tuple ('hori', 'vert') and passes it to sstruct.pack. This is ordinary attribute access in a font-table serializer, with no external input controlling the name.
-
= in : =likely benign Sets bitmap-size table attributes from parsed XML elements whose names are validated against known lists.Reasoning
During XML import, the name is either a known direction key or a name from the fixed dataNames list, and the value goes through safeEval. Unknown names are logged and ignored, so this is a controlled setattr pattern in a font-table parser.
-
in : =likely benign Assigns data-named attributes from XML values through safeEval, ignoring unknown names.Reasoning
The name is checked against dataNames before assignment, and values are parsed with safeEval rather than eval. Unknown names are discarded with a warning. This is standard fontTools XML round-trip code.
-
=likely benign Sets metric attributes from XML, guarded by a fixed name list and safeEval.Reasoning
Same pattern: the name is guarded by membership in metricNames and the value goes through safeEval. Routine XML deserialization for a font table.
-
= -
= -
<> < = => <! -
= -
-
= -
= -
-
-
= -
-
= -
= -
-
-
continuelikely benign Evaluates a conditional expression from the OpenType table spec to decide whether a field is present.Reasoning
eval evaluates conv.aux, a condition string compiled from fontTools' own OpenType table specifications (otData), not from untrusted input. This is a deliberate design for conditional fields in a font-format library, though eval is a broad primitive.
-
continue =likely benign Evaluates a spec-defined conditional aux expression during binary font table decoding.Reasoning
Same as the other otBase eval: conv.aux comes from the trusted internal OpenType spec and is evaluated against the table dictionary during binary read. Benign design, though it uses eval.
-
continuelikely benign Evaluates a spec-defined conditional expression while compiling an OpenType table.Reasoning
The eval input is the spec-defined conv.aux expression from the internal otData definitions. It runs during table compilation and is not driven by attacker input.
-
continue =likely benign Evaluates a spec-defined aux condition against the object's attributes.Reasoning
Same pattern: conv.aux is from the internal OpenType table specification and is evaluated against the object's attributes during XML/object handling. Legitimate, though eval is a broad primitive.
-
= =likely benign Resolves a converter class from the internal OpenType spec type string.Reasoning
spec.type is a converter class name from the internal otData table specification, resolved in a controlled namespace. This is how fontTools maps spec strings to converter classes, not a payload path.
-
= = = or inlikely benign Compiles a spec-defined aux condition string into a code object for later evaluation.Reasoning
compile() is applied to self.aux, which comes from the internal OpenType spec, and is used only as a condition expression. Developer-defined and standard for this library.
-
continue =likely benign Evaluates a spec-defined aux condition against the table's attributes.Reasoning
Same as the other eval calls on conv.aux: the expression comes from the trusted OpenType spec and is evaluated against the table's attributes.
-
= -
= -
= blikely benign A bytes literal of TrueType instruction bytes written as octal escapes in the font program module.Reasoning
The raw pass flags a long bytes literal of octal escapes. It is TrueType bytecode, which is expected in a font-instruction module, likely test or reference data for the disassembler. Raw-pass findings carry a high false-positive rate, and nothing here executes or decodes a payload.
-
=likely benign Reads the deprecated verbose and quiet arguments through locals() to warn about them.Reasoning
locals() is read only to pick up deprecated keyword arguments (verbose, quiet) from a fixed tuple of names. This is ordinary argument-handling code with no execution or hidden behavior.
-
# If pyTag is found in the ImportError message,likely benign Dynamically imports a fontTools table module named by a four-character table tag.Reasoning
The import name is a fixed prefix plus a table tag, and the ImportError is caught to handle unknown tables. The import is confined to the fontTools.ttLib.tables namespace, which is a standard plugin-loading pattern in fontTools. The tag comes from font data, so a crafted tag can only select an existing module in that package.
-
-
-
) = =likely benign Runs a diff command through os.popen in a round-trip test utility.Reasoning
This is a developer test script that shells out to a diff command assembled at runtime. It is a genuine shell call, so it is not a pure false positive, but it is a dev utility rather than a dropper, and nothing in the snippet shows untrusted input reaching the command.
-
lookup slashcontext chained⟨U+000D⟩⟨U+000D⟩RightToLeft no⟨U+000D⟩IgnoreBaseGlyphs no⟨U+000D⟩IgnoreLigatures no⟨U+000D⟩IgnoreMarks no⟨U+000D⟩⟨U+000D⟩backtrackcoverage definition begin⟨U+000D⟩zero⟨U+000D⟩one⟨U+000D⟩two⟨U+000D⟩three⟨U+000D⟩four⟨U+000D⟩five⟨U+000D⟩six⟨U+000D⟩seven⟨U+000D⟩eight⟨U+000D⟩nine⟨U+000D⟩coverage definition end⟨U+000D⟩⟨U+000D⟩inputcoverage definition begin⟨U+000D⟩slash⟨U+000D⟩coverage definition end⟨U+000D⟩⟨U+000D⟩lookaheadcoverage definition begin⟨U+000D⟩zero⟨U+000D⟩one⟨U+000D⟩two⟨U+000D⟩ -
⟨U+000D⟩lookup i-ligatures-deva context⟨U+000D⟩⟨U+000D⟩class definition begin⟨U+000D⟩ivowelsigndeva 1⟨U+000D⟩ivowelsign1deva 1⟨U+000D⟩ivowelsign2deva 1⟨U+000D⟩anusvaradeva 2⟨U+000D⟩candrabindudeva 3⟨U+000D⟩rephdeva 4⟨U+000D⟩rephanusvaradeva 5⟨U+000D⟩class definition end⟨U+000D⟩⟨U+000D⟩class 1,0,0,0,2 1,i-anusvara-deva 5,removemark-deva⟨U+000D⟩class 1,0,0,0,4 1,i-reph-deva 5,removemark-deva⟨U+000D⟩class 1,0,0,0,5 1,i-repha -
lookup slashcontext context⟨U+000D⟩⟨U+000D⟩RightToLeft no⟨U+000D⟩IgnoreBaseGlyphs no⟨U+000D⟩IgnoreLigatures no⟨U+000D⟩IgnoreMarks no⟨U+000D⟩⟨U+000D⟩coverage definition begin 0⟨U+000D⟩zero⟨U+000D⟩one⟨U+000D⟩two⟨U+000D⟩three⟨U+000D⟩four⟨U+000D⟩five⟨U+000D⟩six⟨U+000D⟩seven⟨U+000D⟩eight⟨U+000D⟩nine⟨U+000D⟩coverage definition end⟨U+000D⟩⟨U+000D⟩coverage definition begin 1⟨U+000D⟩slash⟨U+000D⟩coverage definition end⟨U+000D⟩⟨U+000D⟩coverage definition begin 2⟨U+000D⟩zero⟨U+000D⟩one⟨U+000D⟩two⟨U+000D⟩three⟨U+000D⟩four⟨U+000D⟩fiv -
lookup topmarktobase-guru mark to base⟨U+000D⟩⟨U+000D⟩mark bindigurmukhi 0 -184, 1183 16⟨U+000D⟩base ngagurmukhi 0 816, 1183 41⟨U+000D⟩base tthagurmukhi 0 816, 1183 30⟨U+000D⟩base nnagurmukhi 0 976, 1183 35⟨U+000D⟩base nagurmukhi 0 816, 1183 32⟨U+000D⟩base lagurmukhi 0 996, 1183 46⟨U+000D⟩base lanuktagurmukhi 0 996, 1183 46⟨U+000D⟩mark eematragurmukhi 0 -184, 1183 15 -
⟨U+000D⟩lookup supsToInferiors single⟨U+000D⟩⟨U+000D⟩RightToLeft no⟨U+000D⟩IgnoreBaseGlyphs no⟨U+000D⟩IgnoreLigatures no⟨U+000D⟩IgnoreMarks no⟨U+000D⟩⟨U+000D⟩y placement asuperior -560⟨U+000D⟩y placement bsuperior -560⟨U+000D⟩y placement csuperior -560⟨U+000D⟩y placement dsuperior -560⟨U+000D⟩y placement esuperior -560⟨U+000D⟩y placement fsuperior -560⟨U+000D⟩y placement gsuperior -560⟨U+000D⟩y placement hsuperior -560⟨U+000D⟩ -
lookup arabicReverse reversechained⟨U+000D⟩⟨U+000D⟩RightToLeft yes⟨U+000D⟩IgnoreBaseGlyphs no⟨U+000D⟩IgnoreLigatures no⟨U+000D⟩IgnoreMarks yes⟨U+000D⟩⟨U+000D⟩⟨U+000D⟩backtrackcoverage definition begin⟨U+000D⟩bayi1⟨U+000D⟩jeemi1⟨U+000D⟩kafi1⟨U+000D⟩ghafi1⟨U+000D⟩laami1⟨U+000D⟩kafm1⟨U+000D⟩ghafm1⟨U+000D⟩laamm1⟨U+000D⟩coverage definition end⟨U+000D⟩⟨U+000D⟩rayf2 rayf1⟨U+000D⟩reyf2 reyf1⟨U+000D⟩zayf2 zayf1⟨U+000D⟩yayf2 yayf1⟨U+000D⟩⟨U+000D⟩% subtable⟨U+000D⟩⟨U+000D⟩backtrackcoverage definition begin⟨U+000D⟩b -
, , % , )dismissed Calls the fontTools TupleVariation compile method for a round-trip test, not the builtin compile.Reasoning
The matched call is decompile(compile(points)), where compile is the fontTools TupleVariation method for serializing point sets. It is not Python's builtin compile, so the rule matched on a name alone.
-
=dismissed Serializes point sets through the fontTools compile method in a unit test.Reasoning
This is the fontTools compile method serializing point sets in a unit test. It is not dynamic code evaluation.
-
dismissed Serializes an empty set through the fontTools compile method in a unit test.
Reasoning
Same pattern as the other compile matches: a fontTools serialization method exercised by a test, matched by name only.
-
dismissed Serializes delta lists through the fontTools compile method in a round-trip test.
Reasoning
The matched call is the fontTools compile method applied to a list of deltas in a test. It is not builtin compile and does not evaluate strings.
-
-
-
-
likely benign Looks up optional test requirements in globals() to skip tests when a module is missing.
Reasoning
globals() is indexed with requirement names from a fixed TEST_REQUIREMENTS table to decide whether to skip a test. This is standard pytest skip logic with no hidden behavior.
-
-
= =likely benign Executes test fixture outline code to draw a glyph in a GLIF1 test.Reasoning
exec runs Python outline source from a test fixture against a restricted namespace containing only a glyph and a pen. It is a test harness for drawing glyphs, and the source comes from literal test data in the repository.
-
-
= =likely benign Executes test fixture outline code to draw a glyph in a GLIF2 test.Reasoning
Same harness as the GLIF1 test: exec of repository-literal test outline code against a glyph and pen namespace.
-
-
=likely benign Executes outline text from a test helper against a point pen.Reasoning
This test helper execs outline text joined from literal test data, with only a point pen in scope. It is a test utility and the input is not attacker-controlled.
Reproduce This Scan
Run disclude locally to verify. Add --format sarif for SARIF output. Add --llm (with an API key in the environment) to include the LLM review.
&&