`EventScrubber` doesn't scrub a request body that's a top level JSON array

Offen Anfängerfreundlich
#7,543 1 Kommentar 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

Bewertung

Schwierigkeit
2/5
Geschätzter Aufwand
1-3 Stunden
Anfängerfreundlichkeit
78/100
Issue-Typ
Bug
Klarheit
Klar beschrieben
Aktivitätsstatus
Aktiv
Tech-Stack
flask, python
Bereich
security

Rechercherichtung

Reproduziere das Problem mit dem bereitgestellten repro.py und untersuche anschließend EventScrubber.scrub_request, scrub_dict und scrub_list, um nachzuverfolgen, wie Request-Daten verarbeitet werden. Verwende die vorhandenen Scrubber-Tests oder ergänze eine Abdeckung für ein Array auf oberster Ebene; fertig ist die Aufgabe, wenn verschachtelte password- oder api_key-Werte in Array-Bodies genauso gefiltert werden wie in Objekt-Bodies.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Beschreibung

Waiting for: Product Owner
How do you use Sentry?

Sentry Saas (sentry.io)

Version

2.69.2 (also on master at 494ecb3)

Steps to Reproduce

When a request body parses to a top level JSON array, nothing in it gets scrubbed. The same secrets in an object body are filtered normally. No event_scrubber argument, no _experiments data collection config, default max_request_body_size. The integration and the transport in the snippet are only there to catch the event.

A top level array is the usual shape for a bulk endpoint, something like POST /api/v1/users/bulk with a list of records. If those records carry a password or an api_key, they leave the process in the clear. A team that spot checks a single object endpoint sees scrubbing work fine, so there's nothing to tip them off.

Python 3.13.15, Flask 3.1.3, sentry-sdk 2.69.2. Save this as repro.py and run it.

import json
import logging

import sentry_sdk
from flask import Flask
from sentry_sdk.integrations.flask import FlaskIntegration

events = []


class Capture(sentry_sdk.transport.Transport):
    def capture_envelope(self, envelope):
        for item in envelope.items:
            if item.headers.get("type") == "event":
                events.append(item.payload.json)


sentry_sdk.init(
    dsn="https://public@example.com/1",
    integrations=[FlaskIntegration()],
    transport=Capture(),
)

app = Flask(__name__)
app.logger.disabled = True
logging.getLogger("werkzeug").disabled = True


@app.route("/bulk", methods=["POST"])
def bulk():
    raise ValueError("boom")


@app.route("/single", methods=["POST"])
def single():
    raise ValueError("boom")


client = app.test_client()
client.post("/bulk", json=[{"user": "a", "password": "hunter2"}])
client.post("/single", json={"user": "a", "password": "hunter2"})
sentry_sdk.get_client().close()

print("array body :", json.dumps(events[0]["request"]["data"]))
print("object body:", json.dumps(events[1]["request"]["data"]))
Expected Result

The array body should come out filtered the same way the object body does:

array body : [{"password": "[Filtered]", "user": "a"}]
object body: {"password": "[Filtered]", "user": "a"}
Actual Result
array body : [{"password": "hunter2", "user": "a"}]
object body: {"password": "[Filtered]", "user": "a"}

EventScrubber.scrub_request calls scrub_dict on event["request"]["data"], and scrub_dict returns immediately when what it's given isn't a dict, so a list body stops scrubbing before it starts. The class already ships scrub_list, whose docstring says it walks a list and any nested lists and calls scrub_dict on every dictionary it finds, but it's never called on the request body.

This is separate from #7542, which is about how denylist keys are matched. Here the keys never get looked at at all. I have a fix and tests ready if you want a PR.

Vorherrschende Sprache
Python
Sterne
2.2k
Forks
672
Ø Merge
1 T. 13 Min.
Gemergte PRs (30 T.)
212

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus getsentry/sentry-python

Alle Issues in getsentry/sentry-python

Ähnliche Issues

Weitere Issues zu Python

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.