heygrc
ISO 27001 A.8.33 in code

The data a test doesn't need to be real.

ISO 27001:2022 A.8.33 (test information) is about the data used to test a system, not the system itself: it expects that data to be chosen deliberately and handled with care, not borrowed from production just because it is realistic and convenient. A sample of real customer records makes a test look thorough, but it also carries production's data-protection obligations into an environment that may not have been reviewed for whether it can hold them. The control does not ban production-shaped data in testing; it expects that data to be handled with safeguards suited to what it actually contains, usually by generating it synthetically or masking it before it leaves production.

How it shows up in a diff

The shapes the same control failure takes.

A.8.33 rarely breaks by someone deciding to test with live customer data on purpose. It breaks when a masking step gets treated as optional. The recurring shapes:

  • A masking step is skipped or commented out

    A seed or export job that anonymizes production records before loading them into a test environment gets its masking call disabled, usually temporarily, to make a slow export faster or to debug why the masked version looked wrong.

  • The access controls around it never get reviewed

    Real production data lands in a staging or QA environment that was scoped for synthetic fixtures, and the access list, logging, and retention that were set up for synthetic data stay as they were, without anyone checking whether they still fit what the environment now holds.

  • A fixture generator is swapped for a live export

    A test suite that used to generate or load synthetic fixtures is pointed at a fresh pull from production instead, to get volume or edge cases the synthetic generator didn't cover.

  • Test data outlives the test

    A one-off import of production-derived records for a specific test run is never deleted afterward, so it sits in the test environment indefinitely instead of for the duration of the test.

  • Real values leak into test output

    A test run logs, snapshots, or reports the actual field values it operated on instead of a redacted form, so a real email, name, or identifier ends up in a build log or test-report artifact a wider audience can read.

Worked example

A seed script that stopped anonymizing a production sample.

QA needs a realistic volume of customer records to test a new search feature, more than the synthetic fixture generator produces. A nightly job already exports a sample of production customers into staging for exactly this, with an anonymization pass that replaces names and emails with synthetic ones before the load. The anonymization pass roughly triples the export's runtime, and the perf test needs the data loaded before end of day, so the fix is to skip it, with a comment to turn it back on after.

scripts/seed-staging-data.ts+1 -1
const sample = await exportProductionSample(10_000)-await anonymizeRecords(sample)+// await anonymizeRecords(sample) // skip for today's perf test, re-enable afterawait loadIntoStaging(sample)
heygrcISO 27001:2022 A.8.33

This comments out the anonymizeRecords call between the production export and the staging load, so the 10,000-record sample reaches staging without the anonymization pass that normally runs on it. The comment frames the skip as a one-day fix for today's perf test, but the diff does not show anything that re-enables the call afterward or removes this load once the test is done. A.8.33 expects data used in testing to get safeguards suited to what it contains, so confirm the anonymization call gets restored, and check whether this load should be deleted once the perf test is done or whether staging's access controls and retention still fit a dataset that is, for now, unmasked production data.

What an auditor does with this

Auditors ask what's in your test data, not just where it lives.

In an ISO 27001 audit, A.8.33 usually comes up as a question about test data provenance: where the data running in test and staging environments came from, whether any of it is production-derived, and if so, what was done to it before it landed there. A masking step that got skipped for one urgent export is the kind of gap that's invisible from the outside: the environment still looks like 'just staging', while what it actually holds has quietly changed. The pull request that disabled the masking call is the cheapest place to catch that change before it ships.

What this is, and is not

A review, not your data pipeline.

heygrc flags changes that load production-derived data into a test or staging environment without the masking or anonymization step that normally protects it, and cites A.8.33 so the fix happens in the pull request. It does not run your export jobs or manage your test environments. It catches the moment a masking step gets skipped on the way into a test environment, at the diff.