Logs and error trackers copy request bodies, URLs and user fields by default, so student names, grades and messages end up in tools with different access rules than your database. Fix it by inventorying what you capture, masking at the source, restricting access and testing with fake sensitive values.
Why it matters
FERPA protects education records and the personally identifiable information in them, according to the Department of Education. A copy of that data in a log pipeline is still data about a student. If the tool is a third party, it is also a subprocessor to consider under the redisclosure limits in section 99.33(a).
Debugging tools were built for speed, not for data minimisation, so the defaults are generous.
Where student data leaks
- Request and response bodies logged on errors
- URLs with student IDs or names in the path or query string
- Exception messages that include a record
- Session replay and analytics that record form input
- Debug logs left on in production
- Database query logs with literal values
Step 1: find it
Write a handful of fake students with unmistakable values, such as a name like ZZ Testcase and an ID that appears nowhere else. Use the app, trigger errors, then search every log store and tracker for those strings. Whatever you find is real exposure.
Step 2: mask at the source
Filtering downstream leaves the raw data in transit. Better options:
- Use an allow list of fields that may be logged
- Replace identifiers with opaque internal keys
- Drop bodies from error reports by default
- Configure replay tools to mask all inputs and then unmask only safe ones
- Keep identifiers out of URLs, using POST or opaque tokens
Step 3: set retention and access
Choose short retention for debug level logs. Limit who can read production logs, and log those reads. Separate staging from production, and never copy real student data to staging.
Step 4: stop regressions
Add a test that fails if a known sensitive field name appears in a log line. Review new logging in code review. Treat a new observability vendor like a new subprocessor, with a data flow check before it goes live.
A note on code dependencies
Logging libraries and SDKs are dependencies too, and some capture more than expected after an update. Pin versions and review changes. Safeguard's dependency scanning and SBOMs help you track those packages and spot newly added ones in pull requests. It does not read your runtime logs, so the fake data test above is still needed.
Ownership
Give the logging pipeline a named owner, just as you would a database. That person approves new log sources, signs off on retention and runs the fake data test every quarter. Without an owner, each team adds its own tool, and nobody can say where student data is. Add the pipeline to the subprocessor review so any outside observability vendor is checked against the same limits as other vendors.
Quick check
Is hashing a student ID enough to make it safe in logs?
Not always. A hash of a guessable ID can be reversed by trying values. Prefer random internal keys that map back only inside your system.
Sources
Last reviewed: 19 October 2026.