PyPI / posthog / 7.73.1

posthog 7.73.1

Source
https://github.com/posthog/posthog-python
Tag scanned
posthog-v7.73.1
Compared with
posthog-v7.73.0 (0 signals introduced since)
Files
430 scanned, 278 skipped (binary, oversized, or unrecognised)
Signals
0 critical · 0 warn · 10 info
Scan time
9.6 s
LLM review
Reviewed by claude-haiku-5-5 (Anthropic): 9 of 9 warn and critical signals; 9 demoted to info.
Disclude version
4.0.0
Scanned (UTC)
2026-10-21 10:41

Signals

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

  1. info warn → info by review dynamic-execution examples/example-ai-openai-agents/multi_agent.py:29:23

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

            return "Error: invalid characters"
        return f"Result: {eval(expression.replace('^', '**'))}"
    likely benign LLM, confidence 0.70 A calculator tool in an agent example evaluates a math expression with eval after replacing ^ with **.
    Reasoning

    eval runs on an expression that is first filtered for invalid characters, which narrows the input, but eval on agent-supplied text is still a code-injection risk if the filter is incomplete. It is an example calculator, not a dropper or hidden payload.

  2. info warn → info by review dynamic-execution examples/example-ai-openai-agents/single_agent.py:29:23

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

            return "Error: invalid characters"
        return f"Result: {eval(expression.replace('^', '**'))}"
    likely benign LLM, confidence 0.70 A single-agent calculator example evaluates a math expression with eval after a character check.
    Reasoning

    Same calculator pattern as multi_agent.py, with the same character filter before eval. It is a demo of tool use and has no hidden or encoded logic, but the eval is still a risky pattern to copy.

  3. info warn → info by review frame-introspection posthog/exception_utils.py:1060:21

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

            try:
                frame = sys._getframe(depth)
                depth += 1
            except ValueError:
    dismissed LLM, confidence 0.92 Walks the call stack with sys._getframe to collect frames for exception reports.
    Reasoning

    sys._getframe is used in a loop that walks stack frames for exception reporting, a standard technique in error-tracking libraries. It has no network, execution, or hidden behavior.

  4. info warn → info by review encoding-base64 posthog/test/mcp/test_session_token.py:68:15

    base64-like blob (95 bytes, compression ratio 1.12) (raw pass, confidence 0.60)

        )
        frozen = "eyJzaWQiOiJzZXNfZml4dHVyZSIsImNuIjoiQ2xhdWRlIENvZGUiLCJjdiI6IjEuMi4zIiwicHYiOiIyMDI1LTA2LTE4In0"
    
        # Encode side: our output is byte-identical to the shared wire format.
    likely benign LLM, confidence 0.90 A base64 test fixture encoding a session token for a wire-format round-trip test.
    Reasoning

    The string decodes to a small JSON object with session and version fields, used as a fixed test vector for a wire format. It is a test fixture, not an obfuscated payload.

  5. info warn → info by review decoder-decompress-payload posthog/test/test_capture_v1.py:456:24

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

            self.assertEqual(call["data"][0], 0x78)  # zlib header
            roundtripped = zlib.decompress(call["data"]).decode("utf-8")
            self.assertNotIn("api_key", json.loads(roundtripped))
    dismissed LLM, confidence 0.95 Test code decompresses the zlib body of a captured request to assert the API key is not leaked.
    Reasoning

    The test decompresses a zlib payload it just captured from its own client call to check that the api_key is absent. This is ordinary test verification of the library's own output.

  6. info warn → info by review decoder-decompress-payload posthog/test/test_metrics.py:55:23

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

        body = kwargs.get("data")
        return json.loads(gzip.decompress(body).decode("utf-8"))
    dismissed LLM, confidence 0.95 Test helper gunzips a mocked request body to parse its JSON for assertions.
    Reasoning

    The test helper gunzips the request body that the client sent to a mock, then parses the JSON for assertions. This is normal test plumbing.

  7. info warn → info by review decoder-decompress-payload posthog/test/test_request.py:227:27

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

            self.assertEqual(headers["Content-Encoding"], "gzip")
            body = json.loads(gzip.decompress(data))
            self.assertEqual(body["batch"], [])
            self.assertEqual(body["api_key"], TEST_API_KEY)
    dismissed LLM, confidence 0.95 Test gunzips captured request data to verify its batch and API key contents.
    Reasoning

    The test gunzips the request data it captured and checks the batch and api_key fields. This is ordinary verification of the client's own compressed output.

  8. info warn → info by review decoder-decompress-payload posthog/test/tracing/test_client_traces.py:60:23

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

        args, kwargs = session.post.call_args
        return json.loads(gzip.decompress(kwargs["data"])), args[0], kwargs
    dismissed LLM, confidence 0.95 Test helper gunzips a mocked POST body to inspect the sent trace payload.
    Reasoning

    The helper gunzips the body from a mocked session.post call so the trace test can inspect it. The decompression operates on data the test itself generated.

  9. info warn → info by review decoder-decompress-payload posthog/test/tracing/test_transport.py:71:27

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

            assert kwargs["headers"]["Content-Type"] == "application/json"
            assert json.loads(gzip.decompress(kwargs["data"])) == PAYLOAD
    
        def test_falls_back_to_the_default_timeout(self):
    dismissed LLM, confidence 0.95 Transport test gunzips a mocked request body and compares it to the expected payload.
    Reasoning

    The transport test gunzips the mocked request body and compares it to the expected payload. This is standard test verification with no runtime payload execution.

  10. line length 1545 characters (raw pass, confidence 0.50)

    class posthog.client.Client(project_api_key: str, host=None, debug=False, max_queue_size=10000, send=True, on_error=None, flush_at=100, flush_interval=5.0, gzip=False, max_retries=3, sync_mode=False, timeout=15, thread=1, poll_interval=30, personal_api_key=None, disabled=False, disable_geoip=True, is_server=True, histo

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.0.0
git clone https://github.com/posthog/posthog-python posthog-python && cd posthog-python
git checkout posthog-v7.73.1
disclude scan --severity info --diff posthog-v7.73.0 .