PyPI / pip / 26.2.2

pip 26.2.2

Source
https://github.com/pypa/pip
Tag scanned
26.2.2
Compared with
26.2.1 (0 signals introduced since)
Files
803 scanned, 215 skipped (binary, oversized, or unrecognised)
Signals
0 critical · 0 warn · 149 info
Scan time
26.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.1.0
Scanned (UTC)
2026-10-21 23:17

Signals

Ordered by severity, then signals introduced in this release. Hidden characters are shown as ⟨U+…⟩.

  1. info warn → info by review unicode-zero-width AUTHORS.txt:798:2

    U+200B ZERO WIDTH SPACE in source (raw pass, confidence 0.75)

    Sylvain
    S⟨U+200B⟩age Abdullah
    Takayuki SHIMIZUKAWA
    Taneli Hukkinen
    likely benign LLM, confidence 0.97 A zero-width space appears inside a contributor name in AUTHORS.txt.
    Reasoning

    A single zero-width space inside a author name in a plain-text contributors list is a typographic artifact from name entry, not code; no execution context exists.

  2. info critical → info by review dynamic-execution docs/html/user_guide.rst:924:5

    [markup prose] `eval` called on a dynamic (variable/substitution) expression (ast pass, confidence 0.90)

        eval "`pip completion --bash`"
    likely benign LLM, confidence 0.85 RST docs show eval of pip completion output for bash setup.
    Reasoning

    This is documentation showing shell completion setup via eval of pip's own output; it is a documented, well-known pattern in a docs file, not executed code, though the pattern is normally a user-run instruction.

  3. compression ratio 0.764 is >2σ above file mean 0.626 (raw pass, confidence 0.50)

    > "I would like some security advisor, [like in npm]https://docs.npmjs.com/auditing-package-dependencies-for-security-vulnerabilities - it works very well, when you install a package "there are security vulns. with this package - 1 low, 5 medium, 8 high. I haven't come across security issues with Python packages." **
  4. info warn → info by review dynamic-execution src/pip/_internal/commands/configuration.py:248:13

    `subprocess.check_call` called with `shell=True` and a literal command (ast pass, confidence 0.70)

            try:
                subprocess.check_call(f'{editor} "{fname}"', shell=True)
            except FileNotFoundError as e:
                if not e.filename:
    likely benign LLM, confidence 0.80 pip runs the user's editor through subprocess with shell=True for config editing.
    Reasoning

    pip opens the user's configured editor via a shell command; the interpolated editor and filename come from user config and environment, which is expected behavior for an editor launcher, though shell=True with interpolation is a real hygiene concern rather than malice.

  5. info critical → info by review dynamic-import src/pip/_internal/commands/install.py:114:13

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

            try:
                __import__(module)
            except ImportError:
                # Record the module as missing so the hook can raise ImportError
    likely benign LLM, confidence 0.93 Dynamic __import__ used to probe for an optional module during install.
    Reasoning

    This is a standard import-probe in a try block that records missing modules for a hook; the module name is internal and the code is ordinary plugin/import handling.

  6. U+200B ZERO WIDTH SPACE in source (in string/comment) (raw pass, confidence 0.45)

        """Fallback for Python without tarfile.data_filter"""
        # NOTE: This function can be removed once pip requires CPython ≥ 3.12.⟨U+200B⟩
        # PEP 706 added tarfile.data_filter, made tarfile extraction operations more secure.
        # This feature is fully supported from CPython 3.12 onward.
  7. info critical → info by review dynamic-import src/pip/_vendor/__init__.py:33:9

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

        try:
            __import__(modulename, globals(), locals(), level=0)
        except ImportError:
            # We can just silently allow import failures to pass here. If we
    likely benign LLM, confidence 0.95 Vendor package shim imports vendored modules dynamically.
    Reasoning

    This is the vendoring import shim that imports a vendored module by name and silently tolerates ImportError, a well-known legitimate pattern in pip.

  8. info critical → info by review dynamic-import src/pip/_vendor/distlib/resources.py:337:13

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

            if package not in sys.modules:
                __import__(package)
            module = sys.modules[package]
            path = getattr(module, '__path__', None)
    likely benign LLM, confidence 0.93 distlib imports a package by name to find its resource path.
    Reasoning

    Standard distlib resource loading imports a package by name to locate its __path__; ordinary library code.

  9. info critical → info by review dynamic-import src/pip/_vendor/distlib/util.py:680:15

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

        else:
            mod = __import__(module_name)
        if dotted_path is None:
            result = mod
    likely benign LLM, confidence 0.93 distlib resolves a dotted name via __import__.
    Reasoning

    Standard resolver for dotted paths in distlib, importing a module named by a string; typical library behavior.

  10. info unicode-mixed-script src/pip/_vendor/idna/uts46data.py:8850:6

    identifier `ʼn` mixes scripts: Other + Latin (in string/comment) (raw pass, confidence 0.40)

        None,
        "ʼn",
        "ŋ",
        None,
  11. identifier `α` contains homoglyph candidates: α (03B1)→a (in string/comment) (raw pass, confidence 0.35)

        None,
        "α",
        "β",
        "γ",
  12. identifier `η` contains homoglyph candidates: η (03B7)→n (in string/comment) (raw pass, confidence 0.35)

        "ζ",
        "η",
        "θ",
        "ι",
  13. identifier `κ` contains homoglyph candidates: κ (03BA)→k (in string/comment) (raw pass, confidence 0.35)

        "ι",
        "κ",
        "λ",
        "μ",
  14. identifier `ν` contains homoglyph candidates: ν (03BD)→v (in string/comment) (raw pass, confidence 0.35)

        "μ",
        "ν",
        "ξ",
        "ο",
  15. identifier `ο` contains homoglyph candidates: ο (03BF)→o (in string/comment) (raw pass, confidence 0.35)

        "ξ",
        "ο",
        "π",
        "ρ",
  16. identifier `ρ` contains homoglyph candidates: ρ (03C1)→p (in string/comment) (raw pass, confidence 0.35)

        "π",
        "ρ",
        None,
        "σ",
  17. identifier `κ` contains homoglyph candidates: κ (03BA)→k (in string/comment) (raw pass, confidence 0.35)

        None,
        "κ",
        "ρ",
        "σ",
  18. identifier `ρ` contains homoglyph candidates: ρ (03C1)→p (in string/comment) (raw pass, confidence 0.35)

        "κ",
        "ρ",
        "σ",
        None,
  19. identifier `і` contains homoglyph candidates: і (0456)→i (in string/comment) (raw pass, confidence 0.35)

        "ѕ",
        "і",
        "ї",
        "ј",
  20. identifier `а` contains homoglyph candidates: а (0430)→a (in string/comment) (raw pass, confidence 0.35)

        "џ",
        "а",
        "б",
        "в",
  21. identifier `е` contains homoglyph candidates: е (0435)→e (in string/comment) (raw pass, confidence 0.35)

        "д",
        "е",
        "ж",
        "з",
  22. identifier `о` contains homoglyph candidates: о (043E)→o (in string/comment) (raw pass, confidence 0.35)

        "н",
        "о",
        "п",
        "р",
  23. identifier `р` contains homoglyph candidates: р (0440)→p (in string/comment) (raw pass, confidence 0.35)

        "п",
        "р",
        "с",
        "т",
  24. identifier `с` contains homoglyph candidates: с (0441)→c (in string/comment) (raw pass, confidence 0.35)

        "р",
        "с",
        "т",
        "у",
  25. identifier `у` contains homoglyph candidates: у (0443)→y (in string/comment) (raw pass, confidence 0.35)

        "т",
        "у",
        "ф",
        "х",
  26. identifier `х` contains homoglyph candidates: х (0445)→x (in string/comment) (raw pass, confidence 0.35)

        "ф",
        "х",
        "ц",
        "ч",
  27. identifier `о` contains homoglyph candidates: о (043E)→o (in string/comment) (raw pass, confidence 0.35)

        "д",
        "о",
        "с",
        "т",
  28. identifier `с` contains homoglyph candidates: с (0441)→c (in string/comment) (raw pass, confidence 0.35)

        "о",
        "с",
        "т",
        "ъ",
  29. identifier `ρ` contains homoglyph candidates: ρ (03C1)→p (in string/comment) (raw pass, confidence 0.35)

        "γ",
        "ρ",
        "φ",
        "χ",
  30. info unicode-mixed-script src/pip/_vendor/idna/uts46data.py:10374:6

    identifier `aʾ` mixes scripts: Latin + Other (in string/comment) (raw pass, confidence 0.40)

        None,
        "aʾ",
        "ṡ",
        None,
  31. info unicode-mixed-script src/pip/_vendor/idna/uts46data.py:12023:6

    identifier `kω` mixes scripts: Latin + Greek (in string/comment) (raw pass, confidence 0.40)

        "mw",
        "kω",
        "mω",
        None,
  32. info unicode-mixed-script src/pip/_vendor/idna/uts46data.py:12024:6

    identifier `mω` mixes scripts: Latin + Greek (in string/comment) (raw pass, confidence 0.40)

        "kω",
        "mω",
        None,
        "bq",
  33. identifier `α` contains homoglyph candidates: α (03B1)→a (in string/comment) (raw pass, confidence 0.35)

        None,
        "α",
        "β",
        "γ",
  34. identifier `η` contains homoglyph candidates: η (03B7)→n (in string/comment) (raw pass, confidence 0.35)

        "ζ",
        "η",
        "θ",
        "ι",
  35. identifier `κ` contains homoglyph candidates: κ (03BA)→k (in string/comment) (raw pass, confidence 0.35)

        "ι",
        "κ",
        "λ",
        "μ",
  36. identifier `ν` contains homoglyph candidates: ν (03BD)→v (in string/comment) (raw pass, confidence 0.35)

        "μ",
        "ν",
        "ξ",
        "ο",
  37. identifier `ο` contains homoglyph candidates: ο (03BF)→o (in string/comment) (raw pass, confidence 0.35)

        "ξ",
        "ο",
        "π",
        "ρ",
  38. identifier `ρ` contains homoglyph candidates: ρ (03C1)→p (in string/comment) (raw pass, confidence 0.35)

        "π",
        "ρ",
        "θ",
        "σ",
  39. identifier `α` contains homoglyph candidates: α (03B1)→a (in string/comment) (raw pass, confidence 0.35)

        "∇",
        "α",
        "β",
        "γ",
  40. identifier `η` contains homoglyph candidates: η (03B7)→n (in string/comment) (raw pass, confidence 0.35)

        "ζ",
        "η",
        "θ",
        "ι",
  41. identifier `κ` contains homoglyph candidates: κ (03BA)→k (in string/comment) (raw pass, confidence 0.35)

        "ι",
        "κ",
        "λ",
        "μ",
  42. identifier `ν` contains homoglyph candidates: ν (03BD)→v (in string/comment) (raw pass, confidence 0.35)

        "μ",
        "ν",
        "ξ",
        "ο",
  43. identifier `ο` contains homoglyph candidates: ο (03BF)→o (in string/comment) (raw pass, confidence 0.35)

        "ξ",
        "ο",
        "π",
        "ρ",
  44. identifier `ρ` contains homoglyph candidates: ρ (03C1)→p (in string/comment) (raw pass, confidence 0.35)

        "π",
        "ρ",
        "σ",
        "τ",
  45. identifier `κ` contains homoglyph candidates: κ (03BA)→k (in string/comment) (raw pass, confidence 0.35)

        "θ",
        "κ",
        "φ",
        "ρ",
  46. identifier `ρ` contains homoglyph candidates: ρ (03C1)→p (in string/comment) (raw pass, confidence 0.35)

        "φ",
        "ρ",
        "π",
        "α",
  47. identifier `α` contains homoglyph candidates: α (03B1)→a (in string/comment) (raw pass, confidence 0.35)

        "π",
        "α",
        "β",
        "γ",
  48. identifier `η` contains homoglyph candidates: η (03B7)→n (in string/comment) (raw pass, confidence 0.35)

        "ζ",
        "η",
        "θ",
        "ι",
  49. identifier `κ` contains homoglyph candidates: κ (03BA)→k (in string/comment) (raw pass, confidence 0.35)

        "ι",
        "κ",
        "λ",
        "μ",
  50. identifier `ν` contains homoglyph candidates: ν (03BD)→v (in string/comment) (raw pass, confidence 0.35)

        "μ",
        "ν",
        "ξ",
        "ο",
  51. identifier `ο` contains homoglyph candidates: ο (03BF)→o (in string/comment) (raw pass, confidence 0.35)

        "ξ",
        "ο",
        "π",
        "ρ",
  52. identifier `ρ` contains homoglyph candidates: ρ (03C1)→p (in string/comment) (raw pass, confidence 0.35)

        "π",
        "ρ",
        "θ",
        "σ",
  53. identifier `α` contains homoglyph candidates: α (03B1)→a (in string/comment) (raw pass, confidence 0.35)

        "∇",
        "α",
        "β",
        "γ",
  54. identifier `η` contains homoglyph candidates: η (03B7)→n (in string/comment) (raw pass, confidence 0.35)

        "ζ",
        "η",
        "θ",
        "ι",
  55. identifier `κ` contains homoglyph candidates: κ (03BA)→k (in string/comment) (raw pass, confidence 0.35)

        "ι",
        "κ",
        "λ",
        "μ",
  56. identifier `ν` contains homoglyph candidates: ν (03BD)→v (in string/comment) (raw pass, confidence 0.35)

        "μ",
        "ν",
        "ξ",
        "ο",
  57. identifier `ο` contains homoglyph candidates: ο (03BF)→o (in string/comment) (raw pass, confidence 0.35)

        "ξ",
        "ο",
        "π",
        "ρ",
  58. identifier `ρ` contains homoglyph candidates: ρ (03C1)→p (in string/comment) (raw pass, confidence 0.35)

        "π",
        "ρ",
        "σ",
        "τ",
  59. identifier `κ` contains homoglyph candidates: κ (03BA)→k (in string/comment) (raw pass, confidence 0.35)

        "θ",
        "κ",
        "φ",
        "ρ",
  60. identifier `ρ` contains homoglyph candidates: ρ (03C1)→p (in string/comment) (raw pass, confidence 0.35)

        "φ",
        "ρ",
        "π",
        "α",
  61. identifier `α` contains homoglyph candidates: α (03B1)→a (in string/comment) (raw pass, confidence 0.35)

        "π",
        "α",
        "β",
        "γ",
  62. identifier `η` contains homoglyph candidates: η (03B7)→n (in string/comment) (raw pass, confidence 0.35)

        "ζ",
        "η",
        "θ",
        "ι",
  63. identifier `κ` contains homoglyph candidates: κ (03BA)→k (in string/comment) (raw pass, confidence 0.35)

        "ι",
        "κ",
        "λ",
        "μ",
  64. identifier `ν` contains homoglyph candidates: ν (03BD)→v (in string/comment) (raw pass, confidence 0.35)

        "μ",
        "ν",
        "ξ",
        "ο",
  65. identifier `ο` contains homoglyph candidates: ο (03BF)→o (in string/comment) (raw pass, confidence 0.35)

        "ξ",
        "ο",
        "π",
        "ρ",
  66. identifier `ρ` contains homoglyph candidates: ρ (03C1)→p (in string/comment) (raw pass, confidence 0.35)

        "π",
        "ρ",
        "θ",
        "σ",
  67. identifier `α` contains homoglyph candidates: α (03B1)→a (in string/comment) (raw pass, confidence 0.35)

        "∇",
        "α",
        "β",
        "γ",
  68. identifier `η` contains homoglyph candidates: η (03B7)→n (in string/comment) (raw pass, confidence 0.35)

        "ζ",
        "η",
        "θ",
        "ι",
  69. identifier `κ` contains homoglyph candidates: κ (03BA)→k (in string/comment) (raw pass, confidence 0.35)

        "ι",
        "κ",
        "λ",
        "μ",
  70. identifier `ν` contains homoglyph candidates: ν (03BD)→v (in string/comment) (raw pass, confidence 0.35)

        "μ",
        "ν",
        "ξ",
        "ο",
  71. identifier `ο` contains homoglyph candidates: ο (03BF)→o (in string/comment) (raw pass, confidence 0.35)

        "ξ",
        "ο",
        "π",
        "ρ",
  72. identifier `ρ` contains homoglyph candidates: ρ (03C1)→p (in string/comment) (raw pass, confidence 0.35)

        "π",
        "ρ",
        "σ",
        "τ",
  73. identifier `κ` contains homoglyph candidates: κ (03BA)→k (in string/comment) (raw pass, confidence 0.35)

        "θ",
        "κ",
        "φ",
        "ρ",
  74. identifier `ρ` contains homoglyph candidates: ρ (03C1)→p (in string/comment) (raw pass, confidence 0.35)

        "φ",
        "ρ",
        "π",
        "α",
  75. identifier `α` contains homoglyph candidates: α (03B1)→a (in string/comment) (raw pass, confidence 0.35)

        "π",
        "α",
        "β",
        "γ",
  76. identifier `η` contains homoglyph candidates: η (03B7)→n (in string/comment) (raw pass, confidence 0.35)

        "ζ",
        "η",
        "θ",
        "ι",
  77. identifier `κ` contains homoglyph candidates: κ (03BA)→k (in string/comment) (raw pass, confidence 0.35)

        "ι",
        "κ",
        "λ",
        "μ",
  78. identifier `ν` contains homoglyph candidates: ν (03BD)→v (in string/comment) (raw pass, confidence 0.35)

        "μ",
        "ν",
        "ξ",
        "ο",
  79. identifier `ο` contains homoglyph candidates: ο (03BF)→o (in string/comment) (raw pass, confidence 0.35)

        "ξ",
        "ο",
        "π",
        "ρ",
  80. identifier `ρ` contains homoglyph candidates: ρ (03C1)→p (in string/comment) (raw pass, confidence 0.35)

        "π",
        "ρ",
        "θ",
        "σ",
  81. identifier `α` contains homoglyph candidates: α (03B1)→a (in string/comment) (raw pass, confidence 0.35)

        "∇",
        "α",
        "β",
        "γ",
  82. identifier `η` contains homoglyph candidates: η (03B7)→n (in string/comment) (raw pass, confidence 0.35)

        "ζ",
        "η",
        "θ",
        "ι",
  83. identifier `κ` contains homoglyph candidates: κ (03BA)→k (in string/comment) (raw pass, confidence 0.35)

        "ι",
        "κ",
        "λ",
        "μ",
  84. identifier `ν` contains homoglyph candidates: ν (03BD)→v (in string/comment) (raw pass, confidence 0.35)

        "μ",
        "ν",
        "ξ",
        "ο",
  85. identifier `ο` contains homoglyph candidates: ο (03BF)→o (in string/comment) (raw pass, confidence 0.35)

        "ξ",
        "ο",
        "π",
        "ρ",
  86. identifier `ρ` contains homoglyph candidates: ρ (03C1)→p (in string/comment) (raw pass, confidence 0.35)

        "π",
        "ρ",
        "σ",
        "τ",
  87. identifier `κ` contains homoglyph candidates: κ (03BA)→k (in string/comment) (raw pass, confidence 0.35)

        "θ",
        "κ",
        "φ",
        "ρ",
  88. identifier `ρ` contains homoglyph candidates: ρ (03C1)→p (in string/comment) (raw pass, confidence 0.35)

        "φ",
        "ρ",
        "π",
        "α",
  89. identifier `α` contains homoglyph candidates: α (03B1)→a (in string/comment) (raw pass, confidence 0.35)

        "π",
        "α",
        "β",
        "γ",
  90. identifier `η` contains homoglyph candidates: η (03B7)→n (in string/comment) (raw pass, confidence 0.35)

        "ζ",
        "η",
        "θ",
        "ι",
  91. identifier `κ` contains homoglyph candidates: κ (03BA)→k (in string/comment) (raw pass, confidence 0.35)

        "ι",
        "κ",
        "λ",
        "μ",
  92. identifier `ν` contains homoglyph candidates: ν (03BD)→v (in string/comment) (raw pass, confidence 0.35)

        "μ",
        "ν",
        "ξ",
        "ο",
  93. identifier `ο` contains homoglyph candidates: ο (03BF)→o (in string/comment) (raw pass, confidence 0.35)

        "ξ",
        "ο",
        "π",
        "ρ",
  94. identifier `ρ` contains homoglyph candidates: ρ (03C1)→p (in string/comment) (raw pass, confidence 0.35)

        "π",
        "ρ",
        "θ",
        "σ",
  95. identifier `α` contains homoglyph candidates: α (03B1)→a (in string/comment) (raw pass, confidence 0.35)

        "∇",
        "α",
        "β",
        "γ",
  96. identifier `η` contains homoglyph candidates: η (03B7)→n (in string/comment) (raw pass, confidence 0.35)

        "ζ",
        "η",
        "θ",
        "ι",
  97. identifier `κ` contains homoglyph candidates: κ (03BA)→k (in string/comment) (raw pass, confidence 0.35)

        "ι",
        "κ",
        "λ",
        "μ",
  98. identifier `ν` contains homoglyph candidates: ν (03BD)→v (in string/comment) (raw pass, confidence 0.35)

        "μ",
        "ν",
        "ξ",
        "ο",
  99. identifier `ο` contains homoglyph candidates: ο (03BF)→o (in string/comment) (raw pass, confidence 0.35)

        "ξ",
        "ο",
        "π",
        "ρ",
  100. identifier `ρ` contains homoglyph candidates: ρ (03C1)→p (in string/comment) (raw pass, confidence 0.35)

        "π",
        "ρ",
        "σ",
        "τ",
  101. identifier `κ` contains homoglyph candidates: κ (03BA)→k (in string/comment) (raw pass, confidence 0.35)

        "θ",
        "κ",
        "φ",
        "ρ",
  102. identifier `ρ` contains homoglyph candidates: ρ (03C1)→p (in string/comment) (raw pass, confidence 0.35)

        "φ",
        "ρ",
        "π",
        "ϝ",
  103. identifier `а` contains homoglyph candidates: а (0430)→a (in string/comment) (raw pass, confidence 0.35)

        None,
        "а",
        "б",
        "в",
  104. identifier `е` contains homoglyph candidates: е (0435)→e (in string/comment) (raw pass, confidence 0.35)

        "д",
        "е",
        "ж",
        "з",
  105. identifier `о` contains homoglyph candidates: о (043E)→o (in string/comment) (raw pass, confidence 0.35)

        "м",
        "о",
        "п",
        "р",
  106. identifier `р` contains homoglyph candidates: р (0440)→p (in string/comment) (raw pass, confidence 0.35)

        "п",
        "р",
        "с",
        "т",
  107. identifier `с` contains homoglyph candidates: с (0441)→c (in string/comment) (raw pass, confidence 0.35)

        "р",
        "с",
        "т",
        "у",
  108. identifier `у` contains homoglyph candidates: у (0443)→y (in string/comment) (raw pass, confidence 0.35)

        "т",
        "у",
        "ф",
        "х",
  109. identifier `х` contains homoglyph candidates: х (0445)→x (in string/comment) (raw pass, confidence 0.35)

        "ф",
        "х",
        "ц",
        "ч",
  110. identifier `і` contains homoglyph candidates: і (0456)→i (in string/comment) (raw pass, confidence 0.35)

        "ә",
        "і",
        "ј",
        "ө",
  111. identifier `а` contains homoglyph candidates: а (0430)→a (in string/comment) (raw pass, confidence 0.35)

        "ӏ",
        "а",
        "б",
        "в",
  112. identifier `е` contains homoglyph candidates: е (0435)→e (in string/comment) (raw pass, confidence 0.35)

        "д",
        "е",
        "ж",
        "з",
  113. identifier `о` contains homoglyph candidates: о (043E)→o (in string/comment) (raw pass, confidence 0.35)

        "л",
        "о",
        "п",
        "с",
  114. identifier `с` contains homoglyph candidates: с (0441)→c (in string/comment) (raw pass, confidence 0.35)

        "п",
        "с",
        "у",
        "ф",
  115. identifier `у` contains homoglyph candidates: у (0443)→y (in string/comment) (raw pass, confidence 0.35)

        "с",
        "у",
        "ф",
        "х",
  116. identifier `х` contains homoglyph candidates: х (0445)→x (in string/comment) (raw pass, confidence 0.35)

        "ф",
        "х",
        "ц",
        "ч",
  117. identifier `і` contains homoglyph candidates: і (0456)→i (in string/comment) (raw pass, confidence 0.35)

        "ґ",
        "і",
        "ѕ",
        "џ",
  118. info warn → info by review dynamic-execution src/pip/_vendor/packaging/licenses/__init__.py:144:9

    `compile` called on a non-literal expression (ast pass, confidence 0.70)

        try:
            compile(python_expression, "", "eval")
        except SyntaxError:
            message = f"Invalid license expression: {raw_license_expression!r}"
    likely benign LLM, confidence 0.90 packaging compiles a license expression purely to check syntax.
    Reasoning

    compile is used only to validate a license expression syntax and the SyntaxError is caught; it is a parse check, not execution.

  119. info critical → info by review dynamic-import src/pip/_vendor/pkg_resources/__init__.py:427:9

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

        except KeyError:
            __import__(moduleOrReq)
            module = sys.modules[moduleOrReq]
        loader = getattr(module, '__loader__', None)
    likely benign LLM, confidence 0.93 pkg_resources imports a module by name when resolving a requirement.
    Reasoning

    Standard pkg_resources namespace import of a requested module; legitimate library behavior.

  120. info critical → info by review frame-introspection src/pip/_vendor/pkg_resources/__init__.py:743:14

    `sys._getframe` — call-stack frame introspection — file also calls `sys.exit`/`exec`/`eval` (anti-analysis shape) (ast pass, confidence 0.85)

            """Locate distribution for `requires` and run `script_name` script"""
            ns = sys._getframe(1).f_globals
            name = ns['__name__']
            ns.clear()
    likely benign LLM, confidence 0.85 pkg_resources run_script reads caller globals via sys._getframe to execute an entry-point script.
    Reasoning

    This is the setuptools-style script runner that inspects the caller's globals to run an entry-point script; sys._getframe with ns.clear is unusual but is the documented mechanism of run_script, and the co-occurrence with exec is expected in this context.

  121. info warn → info by review dynamic-execution src/pip/_vendor/pkg_resources/__init__.py:1713:20

    `compile` called on a non-literal expression (ast pass, confidence 0.70)

                source = _read_utf8_with_fallback(script_filename)
                code = compile(source, script_filename, 'exec')
                exec(code, namespace, namespace)
            else:
    likely benign LLM, confidence 0.90 pkg_resources compiles a distribution's script file for run_script.
    Reasoning

    Executes an installed distribution's own script file within pkg_resources' script runner; this is the library's documented function for running entry-point scripts, with source from local package metadata.

  122. info warn → info by review dynamic-execution src/pip/_vendor/pkg_resources/__init__.py:1714:13

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

                code = compile(source, script_filename, 'exec')
                exec(code, namespace, namespace)
            else:
                from linecache import cache
    likely benign LLM, confidence 0.90 pkg_resources execs a distribution's script in run_script.
    Reasoning

    Same run_script path executing a distribution's own script; legitimate design of the library.

  123. info warn → info by review dynamic-execution src/pip/_vendor/pkg_resources/__init__.py:1724:27

    `compile` called on a non-literal expression (ast pass, confidence 0.70)

                )
                script_code = compile(script_text, script_filename, 'exec')
                exec(script_code, namespace, namespace)
    likely benign LLM, confidence 0.90 pkg_resources compiles script text from distribution metadata for execution.
    Reasoning

    Same script-execution path compiling script text from distribution metadata; expected for run_script functionality.

  124. info warn → info by review dynamic-execution src/pip/_vendor/pkg_resources/__init__.py:1725:13

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

                script_code = compile(script_text, script_filename, 'exec')
                exec(script_code, namespace, namespace)
    
        def _has(self, path) -> bool:
    likely benign LLM, confidence 0.90 pkg_resources execs distribution script text in run_script.
    Reasoning

    Executes compiled script text from the distribution in run_script; legitimate library functionality, not a hidden payload.

  125. info critical → info by review dynamic-import src/pip/_vendor/pkg_resources/__init__.py:2530:17

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

                if parent not in _namespace_packages:
                    __import__(parent)
                try:
                    path = sys.modules[parent].__path__
    likely benign LLM, confidence 0.92 pkg_resources imports a parent namespace package to read its path.
    Reasoning

    Standard namespace-package handling importing a parent package by name before reading its __path__; ordinary library code.

  126. info critical → info by review dynamic-import src/pip/_vendor/pkg_resources/__init__.py:2751:18

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

            """
            module = __import__(self.module_name, fromlist=['__name__'], level=0)
            try:
                return functools.reduce(getattr, self.attrs, module)
    likely benign LLM, confidence 0.90 Dynamic __import__ of an entry point's module name followed by attribute traversal.
    Reasoning

    Standard EntryPoint.resolve pattern in pkg_resources loading a module by configured name; the module name comes from package metadata, which is normal plugin/entry-point loading in vendored setuptools code.

  127. info critical → info by review frame-introspection src/pip/_vendor/pkg_resources/__init__.py:3411:15

    `sys._getframe` — call-stack frame introspection — file also calls `sys.exit`/`exec`/`eval` (anti-analysis shape) (ast pass, confidence 0.85)

            # the pkg_resources module, to use for the warning
            while sys._getframe(level).f_globals is g:
                level += 1
        except ValueError:
    likely benign LLM, confidence 0.85 Call-stack walk to locate the external caller for a warning.
    Reasoning

    sys._getframe in a stack walk to find the caller for warnings.warn stacklevel, a well-known legitimate idiom. The anti-analysis label is a weak heuristic here given the vendored context.

  128. info critical → info by review dynamic-import src/pip/_vendor/pygments/formatters/__init__.py:38:11

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

        """Load a formatter (and all others in the module too)."""
        mod = __import__(module_name, None, None, ['__all__'])
        for formatter_name in mod.__all__:
            cls = getattr(mod, formatter_name)
    likely benign LLM, confidence 0.90 Dynamic import of a bundled Pygments formatter module.
    Reasoning

    Pygments plugin loader importing its own bundled formatter modules by name; standard library-style dynamic import, not hidden payload.

  129. info warn → info by review dynamic-execution src/pip/_vendor/pygments/formatters/__init__.py:103:13

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

            with open(filename, 'rb') as f:
                exec(f.read(), custom_namespace)
            # Retrieve the class `formattername` from that namespace
            if formattername not in custom_namespace:
    likely benign LLM, confidence 0.80 exec of a user-specified custom formatter source file into a namespace.
    Reasoning

    Pygments loads a user-supplied custom formatter file via exec into a namespace, a documented feature requiring a user-chosen local file; it is a plugin mechanism, not covert execution, though exec of a file is a real capability.

  130. info critical → info by review dynamic-import src/pip/_vendor/pygments/lexers/__init__.py:45:11

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

        """Load a lexer (and all others in the module too)."""
        mod = __import__(module_name, None, None, ['__all__'])
        for lexer_name in mod.__all__:
            cls = getattr(mod, lexer_name)
    likely benign LLM, confidence 0.90 Dynamic import of a bundled Pygments lexer module.
    Reasoning

    Same standard Pygments lexer loader importing its bundled lexer modules.

  131. info warn → info by review dynamic-execution src/pip/_vendor/pygments/lexers/__init__.py:154:13

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

            with open(filename, 'rb') as f:
                exec(f.read(), custom_namespace)
            # Retrieve the class `lexername` from that namespace
            if lexername not in custom_namespace:
    likely benign LLM, confidence 0.80 exec of a user-specified custom lexer source file.
    Reasoning

    Documented Pygments feature to load a custom lexer from a user-provided file via exec; consistent with the plugin design.

  132. info critical → info by review dynamic-import src/pip/_vendor/pygments/sphinxext.py:161:19

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

                module = data[0]
                mod = __import__(module, None, None, [classname])
                self.filenames.add(mod.__file__)
                cls = getattr(mod, classname)
    likely benign LLM, confidence 0.90 Dynamic import of a lexer class named in the Sphinx extension data.
    Reasoning

    Sphinx extension resolving a documented lexer class path from docs configuration; standard dynamic import of a user-named class.

  133. info critical → info by review dynamic-import src/pip/_vendor/pygments/sphinxext.py:221:19

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

                module = data[0]
                mod = __import__(module, None, None, [classname])
                self.filenames.add(mod.__file__)
                cls = getattr(mod, classname)
    likely benign LLM, confidence 0.90 Dynamic import of a lexer class in the Sphinx extension.
    Reasoning

    Same Sphinx extension lexer/class resolution pattern as the sibling finding.

  134. info critical → info by review dynamic-import src/pip/_vendor/pygments/styles/__init__.py:45:15

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

        try:
            mod = __import__(mod, None, None, [cls])
        except ImportError:
            raise ClassNotFound(f"Could not find style module {mod!r}" +
    likely benign LLM, confidence 0.90 Dynamic import of a Pygments style module by name.
    Reasoning

    Pygments style loader importing a style module by name with ImportError handling; ordinary plugin loading.

  135. compression ratio 0.629 is >2σ above file mean 0.384 (raw pass, confidence 0.50)

    
    Sc = '$\xa2-\xa5\u058f\u060b\u07fe-\u07ff\u09f2-\u09f3\u09fb\u0af1\u0bf9\u0e3f\u17db\u20a0-\u20bf\ua838\ufdfc\ufe69\uff04\uffe0-\uffe1\uffe5-\uffe6\U0001ecb0'
  136. info warn → info by review dynamic-attribute src/pip/_vendor/pygments/unistring.py:83:20

    reach-by-name through `globals` (ast pass, confidence 0.60)

    def combine(*args):
        return ''.join(globals()[cat] for cat in args)
    likely benign LLM, confidence 0.90 Builds Unicode character ranges by name lookup in module globals.
    Reasoning

    Looks up Unicode category string constants from module globals to combine character classes; a plain data-building idiom with no external input.

  137. info warn → info by review dynamic-attribute src/pip/_vendor/pygments/unistring.py:90:20

    reach-by-name through `globals` (ast pass, confidence 0.60)

            newcats.remove(arg)
        return ''.join(globals()[cat] for cat in newcats)
    likely benign LLM, confidence 0.90 Combines Unicode category constants via globals lookup.
    Reasoning

    Same globals lookup for Unicode category constants, used to generate regex character classes.

  138. info warn → info by review dynamic-execution src/pip/_vendor/pygments/unistring.py:115:10

    `open(__file__)` — file reads its own source, common pattern for extracting payloads hidden in comments (ast pass, confidence 0.85)

    
        with open(__file__, encoding='utf-8') as fp:
            content = fp.read()
    likely benign LLM, confidence 0.90 Reads its own source file as part of a data-generation routine.
    Reasoning

    This is the generator script that rewrites the unistring data module from Unicode data; reading __file__ is for regenerating/inspecting its own source, not extracting a hidden payload.

  139. info warn → info by review dynamic-execution src/pip/_vendor/pygments/unistring.py:139:10

    `open(__file__)` — file reads its own source, common pattern for extracting payloads hidden in comments (ast pass, confidence 0.85)

    
        with open(__file__, 'w', encoding='utf-8') as fp:
            fp.write(header)
    likely benign LLM, confidence 0.90 Rewrites its own module file with generated Unicode tables.
    Reasoning

    Writes a generated header into the same module file during a maintenance/generation routine; a code generator, not covert behavior.

  140. info warn → info by review dynamic-attribute src/pip/_vendor/pyproject_hooks/_in_process/_in_process.py:367:12

    reach-by-name through `globals` (ast pass, confidence 0.60)

    
        hook = globals()[hook_name]
    
        hook_input = read_json(pjoin(control_dir, "input.json"))
    likely benign LLM, confidence 0.90 Looks up a build hook function by name in globals for the in-process backend.
    Reasoning

    pyproject_hooks in-process backend dispatches to a fixed set of hook names from a control request; reaching a hook function by name in globals is its intended design.

  141. info warn → info by review dynamic-attribute src/pip/_vendor/requests/packages.py:10:5

    reach-by-name through `locals` (ast pass, confidence 0.60)

        vendored_package = "pip._vendor." + package
        locals()[package] = __import__(vendored_package)
        # This traversal is apparently necessary such that the identities are
        # preserved (requests.packages.urllib3.* is urllib3.*)
    likely benign LLM, confidence 0.90 Aliases vendored packages under legacy names via locals assignment and __import__.
    Reasoning

    Known requests compatibility shim that aliases vendored urllib3/chardet modules into the sys.modules-style namespace so old imports keep working; benign and documented in the code.

  142. info critical → info by review dynamic-import src/pip/_vendor/requests/packages.py:10:25

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

        vendored_package = "pip._vendor." + package
        locals()[package] = __import__(vendored_package)
        # This traversal is apparently necessary such that the identities are
        # preserved (requests.packages.urllib3.* is urllib3.*)
    likely benign LLM, confidence 0.90 Dynamic __import__ of pip._vendor submodules in the requests compatibility shim.
    Reasoning

    This is the standard vendoring shim that aliases vendored packages under their historical names. The import target is a fixed prefix plus a loop variable over known package names, so it is not attacker-controlled input.

  143. info warn → info by review frame-introspection src/pip/_vendor/rich/console.py:1929:26

    `inspect.stack` — call-stack frame introspection (ast pass, confidence 0.70)

                # Fallback to the slower stack
                frame_info = inspect.stack()[offset]
                return frame_info.filename, frame_info.lineno, frame_info.frame.f_locals
    likely benign LLM, confidence 0.90 Fallback call-stack introspection in rich's console for locating the caller frame.
    Reasoning

    Rich uses inspect.stack() as a slow fallback to find caller filename and line for logging/printing. This is ordinary library behavior with no exfiltration or hidden execution.

  144. info critical → info by review builtins-write src/pip/_vendor/rich/pretty.py:204:13

    `builtins._ = ...` — patches a built-in for every importer of this module (ast pass, confidence 0.95)

                assert console is not None
                builtins._ = None  # type: ignore[attr-defined]
                console.print(
                    (
    likely benign LLM, confidence 0.85 Temporary assignment to builtins._ in rich's pretty printer, mimicking REPL last-value behavior.
    Reasoning

    Rich's pretty printer sets builtins._ temporarily to mirror the interactive REPL's last-value convention, as in sys.displayhook. It is a known, upstream-documented behavior and it restores state afterward. Flagged as critical by pattern alone, but it is not malicious.

  145. info critical → info by review builtins-write src/pip/_vendor/rich/pretty.py:221:13

    `builtins._ = ...` — patches a built-in for every importer of this module (ast pass, confidence 0.95)

                )
                builtins._ = value  # type: ignore[attr-defined]
    
        try:
    likely benign LLM, confidence 0.85 Second builtins._ assignment in rich's pretty printer restoring REPL-style last-value semantics.
    Reasoning

    Same pattern as the sibling finding: setting builtins._ to the printed value to emulate the REPL's underscore variable, consistent with rich's pretty.py implementation. No hidden payload or persistent hook.

  146. info warn → info by review decoder-decompress-payload src/pip/_vendor/urllib3/response.py:65:21

    file imports decoder module(s) zlib and calls `.decompress()` — embedded payload decompressed at runtime (ast pass, confidence 0.75)

            self._unfed_data = b""
            self._obj = zlib.decompressobj()
    
        def decompress(self, data: bytes, max_length: int = -1) -> bytes:
    likely benign LLM, confidence 0.90 zlib decompressobj used by urllib3 to decode HTTP response content-encoding.
    Reasoning

    This is urllib3's standard streaming decompressor wrapper for HTTP content-encoding (gzip/deflate). zlib.decompressobj on HTTP response bodies is the expected function, not a hidden embedded payload.

  147. identifier `ˈpjœr` mixes scripts: Other + Latin (in string/comment) (raw pass, confidence 0.40)

            sys.stdout.buffer.write(
                "* Björk Guðmundsdóttir [ˈpjœr̥k ˈkvʏðmʏntsˌtoʊhtɪr]".encode()
            )
        else:
  148. identifier `ˈkvʏðmʏntsˌtoʊhtɪr` mixes scripts: Other + Latin (in string/comment) (raw pass, confidence 0.40)

            sys.stdout.buffer.write(
                "* Björk Guðmundsdóttir [ˈpjœr̥k ˈkvʏðmʏntsˌtoʊhtɪr]".encode()
            )
        else:
  149. info critical → info by review dynamic-execution tests/functional/test_no_color.py:35:16

    `subprocess.Popen` with `shell=True` and a non-literal command — runtime-determined shell invocation (ast pass, confidence 0.85)

            cmd = command.format(option)
            proc = subprocess.Popen(
                cmd,
                shell=True,
    likely benign LLM, confidence 0.80 Test helper running a formatted command through subprocess.Popen with shell=True.
    Reasoning

    This is a functional test that formats a command with an option and runs it via shell=True. The command comes from test-controlled data, not untrusted input. Shell use in tests is a poor practice but not evidence of malicious intent.

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.

cargo install disclude --version 4.1.0
git clone https://github.com/pypa/pip pip && cd pip
git checkout 26.2.2
disclude scan --severity info --diff 26.2.1 .