fonttools 4.67.0
- Source
- https://github.com/fonttools/fonttools
- Tag scanned
4.67.0- Compared with
4.66.1(0 signals introduced since)- Files
- 830 scanned, 1814 skipped (binary, oversized, or unrecognised)
- Signals
- 0 critical · 0 warn · 80 info
- Scan time
- 36.9 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-15 07:26
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 decorator resolves function names through globals().Reasoning
Looks up benchmark function names from globals() inside a decorator wrapper. This is a common, ordinary way to resolve a named function in a benchmark helper, not obfuscation.
-
= =likely benign Second globals() name lookup in the same benchmark wrapper.Reasoning
Same globals() name lookup as the neighbouring finding, in a benchmark helper. The pattern is a plain name-to-function lookup with no sign of hidden payload or intent.
-
= continuelikely benign Dynamic import of fontTools tool modules during help discovery, with ImportError ignored.Reasoning
__import__ is called with a loop variable naming fontTools tool packages, and ImportError is caught and skipped. This is plugin-style discovery of the package's own submodules. It is flagged critical only because the argument is non-literal.
-
= Nonelikely benign Fallback stubs for Cython type names installed into module globals.Reasoning
Assigns None into globals() for a fixed tuple of names (double, complex, int) as a fallback when Cython is absent. This is a standard compatibility shim.
-
= =likely benign No-op Cython decorator stubs installed into globals.Reasoning
Installs no-op decorator stubs into globals() for cfunc and inline when Cython is unavailable. This is a standard no-Cython fallback.
-
=likely benign Checks locals() for argument names to validate constructor arguments.Reasoning
Reads locals() for fixed argument names to validate that msg and level are not passed without a logger. This is ordinary argument checking.
-
pass -
-
: is or . is , -
= = + -
= =likely benign CLI helper evals user-supplied expression strings from sys.argv.Reasoning
eval is applied to command-line arguments in a developer CLI that builds pen-drawing expressions. It is a real code-execution path for whoever runs the tool, but it is intended behaviour for a local utility and does not look like hidden or supply-chain malice.
-
= =likely benign Benchmark decorator resolves function names through globals().Reasoning
Same globals() name lookup pattern as the cu2qu benchmark, in a benchmark helper. Benign.
-
= =likely benign Second globals() name lookup in the qu2cu benchmark wrapper.Reasoning
Second globals() name lookup in the same benchmark wrapper. Benign.
-
"""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 WOFF table data with zlib during font parsing.Reasoning
zlib.decompress on table data in the sfnt/WOFF reader is the standard decompression step for WOFF-compressed tables, with a length check that follows. Expected for a font library.
-
=likely benign XML import sets whitelisted metric attributes via vars() using safeEval values.Reasoning
In the XML fromXML path, it sets an attribute on self by name only after checking the name against a whitelist, with values parsed by safeEval. This is controlled, expected deserialization.
-
-
-
=likely benign XML import sets whitelisted component attributes via vars() using safeEval values.Reasoning
Same whitelisted-name vars() assignment with safeEval, in the EBDT XML reader. Benign.
-
-
= = =likely benign Binary table parser stores metric objects via vars() by name.Reasoning
Binary unpacking assigns a metric object onto a table via vars() for a fixed metric name. This is ordinary table-parsing code.
-
= =likely benign Packs fixed hori/vert metric objects read through vars().Reasoning
Reads metric objects from vars() for the fixed names hori and vert while packing the table. Benign.
-
= in : =likely benign XML import stores direction metrics and whitelisted data fields via vars().Reasoning
XML import stores direction metrics and whitelisted data names via vars() with safeEval values. Benign.
-
in : =likely benign Whitelist-guarded setattr-style assignment while reading EBLC bitmap size table XML.Reasoning
vars(self)[name] is assigned only after `name in dataNames`, a fixed whitelist of attribute names, and the value goes through safeEval. This is ordinary XML-to-object deserialization in fontTools, not an attacker-controlled attribute write.
-
=likely benign Whitelist-guarded attribute assignment from XML metric values.Reasoning
The write is guarded by `name in metricNames`, a fixed set of metric field names, and the value goes through safeEval. This is the same benign XML deserialization pattern.
-
= -
= -
<> < = => <! -
= -
-
= -
= -
-
-
= -
-
= -
= -
-
-
continuelikely benign Evaluates a schema-defined condition expression while reading OpenType data.Reasoning
conv.aux is a condition expression from fontTools' built-in OpenType table definitions (otData), not from the font file. The eval is a documented design choice of the table schema, so the input is trusted.
-
continue =likely benign Evaluates a schema-defined condition expression during table reading.Reasoning
Same as the other otBase eval: conv.aux comes from the built-in otData schema, not untrusted input, so this is a legitimate table-driven condition.
-
continuelikely benign Evaluates a schema-defined condition expression during table decompilation.Reasoning
conv.aux is a built-in OpenType schema expression, and the eval is part of the table-conditional logic of the library.
-
continue =likely benign Evaluates a schema-defined condition expression during table compilation.Reasoning
Same pattern: the eval expression is a trusted otData schema condition, not data from the font file.
-
= =likely benign Resolves a converter class from a schema type string via eval.Reasoning
spec.type is a converter type string from the built-in OpenType schema, evaluated in a controlled namespace. The input is not attacker-controlled, so this is standard fontTools schema dispatch.
-
= = = or inlikely benign Precompiles a schema-defined condition expression for converters.Reasoning
compile() is applied to conv.aux, a schema-defined condition expression from the built-in tables. It is a precompilation step, not runtime injection of untrusted code.
-
continue =likely benign Evaluates a schema-defined condition expression for OpenType table fields.Reasoning
Same trusted otData schema condition evaluated with vars(self), consistent with the rest of the OpenType table machinery.
-
= -
= -
= blikely benign Static bytes literal with octal escape sequences in TrueType program code.Reasoning
The flagged item is a large bytes literal of octal escapes, a static data table in the source. Raw-pass byte-level patterns have a high false-positive rate, and a literal constant like this is not an executed payload or dropper.
-
=likely benign Reads fixed local argument names to emit a deprecation warning.Reasoning
locals().get is used to read the verbose/quiet arguments so a deprecation warning can be emitted. It only reads two fixed names and does not reach arbitrary state.
-
# If pyTag is found in the ImportError message,likely benign Dynamically imports the table module matching a font table tag.Reasoning
The import is prefixed with a fixed package path, so a tag from the font can only load modules under fontTools.ttLib.tables and cannot escape to arbitrary modules. Tag-to-module-name mapping is a standard fontTools pattern. The critical severity overstates the risk, though a malicious tag could still trigger import of an unexpected in-package module.
-
-
-
) = =likely benign Runs a diff shell command via os.popen in a MetaTools round-trip test script.Reasoning
This is a developer test-harness script that runs a diff command to compare round-trip output. The command is built from local file paths, so there is a theoretical shell-injection concern if paths are malicious, but nothing indicates malicious intent or an obfuscated payload.
-
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 Unit test calling a library method named compile on point data.Reasoning
The `compile` here is fontTools' own TupleVariation.compilePoints helper in a unit test, not Python's builtin compile on an untrusted string. The flag comes from name matching alone.
-
=dismissed Test calls a fonttools compile() helper to serialize a set of point indices and checks that decompile() restores it.Reasoning
The call sits in a round-trip unit test where compile() is the fonttools TupleVariation point-packing function, not the Python builtin. The argument is a set of point indices built in the test. Nothing is executed, and the scanner flagged the name alone.
-
dismissed Second round-trip assertion using the same fonttools compile()/decompile() helpers on an empty set.
Reasoning
Same pattern as the neighbouring finding: a fonttools serialization helper is round-tripped in a unit test on locally built data. The builtin-compile reading does not apply, so this is a false positive from the name match.
-
dismissed Test round-trips a shuffled deltas list through the fonttools compile/decompile helpers.
Reasoning
A fonttools delta-compile helper is applied to a locally shuffled list in a test and then decompiled to check the round trip. It is a data serialization test, not dynamic code execution.
-
-
-
-
likely benign Test checks whether optional dependencies are importable via a globals() lookup and skips if any is missing.
Reasoning
The test looks up optional-requirement flags by name in globals() to decide whether to skip a test when a module is missing. The keys come from a fixed TEST_REQUIREMENTS table in the test file. This is a common, benign pytest idiom.
-
-
= =likely benign GLIF1 test execs a fixture drawing script against a Glyph and point pen to generate expected glif output.Reasoning
exec runs Python source that is part of the test fixture, here a drawing script for a glyph. The namespace is limited to the test's own glyph and pen objects. The snippet shows no network, file, or shell activity. It is a test harness, though exec is still a sensitive primitive.
-
-
= =likely benign GLIF2 test execs a fixture drawing script against a Glyph and point pen to build a glyph for comparison.Reasoning
This is the GLIF2 counterpart of the GLIF1 finding. It runs fixture drawing code in a restricted namespace to build a glyph for serialization comparison. Nothing in the snippet is malicious.
-
-
=likely benign Test helper execs a joined outline script against a point pen to produce glyph drawing calls.Reasoning
A test support helper joins a list of outline lines and execs them with a point pen in the namespace. The source is the test's own outline data, not external input. This is a test-fixture pattern, though exec is worth a note.
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.
&&