Skip to content

About

Artifact for 'Papers, Please: A First Look at Age Verification on the Web' (IEEE S&P 2026)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Papers, Please Artifact

This repository includes artifacts for "Papers, Please: A First Look at Age Verification on the Web" which is to appear at IEEE S&P 2026.

Here, we include our web crawling code, code to detect 3rd party providers, code to analyze the prevalence of the top providers, artifacts from reverse-engineering Yoti's face capture module, and a proof-of-concept browser extension to bypass Yoti's age estimation method (tested with SCM 2.8.0).

@inproceedings{minocha_papersplease_2026,
    title = {Papers, Please: A First Look at Age Verification on the Web},
    author = {Minocha, Shreyas and Sheridan, Isaac and Oppenheimer, Harry and Pearce, Paul and Specter, Michael A.},
    year = {2026},
    month = may,
    booktitle = {IEEE Symposium on Security and Privacy},
    url = {https://shreyasminocha.me/papers/papers-please.pdf},
    doi = {10.1109/SP63933.2026.00161},
}

Artifact Evaluation Quickstart

  1. Set up a uv environment in analysis with uv sync, extract the .gz files in analysis/data, run prevalence.ipynb, and check that the numbers computed in the notebook match the quoted text.
  2. Check that the partially reverse-engineered Yoti SICAP code and a SICAP bypass PoC are included in yoti-scm-re and yoti-sicap-bypass respectively.
  3. Check that the code to run detectors against webpages is included in analysis/src/prevalence/run_detectors.py.
  4. Check that the code to crawl webpages is included in crawl and the code to fetch data from Klazify is included in analysis/src/klazify.

Resources

It should be possible to run everything but the web crawling code on Google Colab.

Components

  • crawl/: Web crawling code (Section 3.1.3)

    Although we include this for completeness and for ease of replication, we do not expect artifact evaluators to replicate our setup. This step requires a significant amount of memory, disk storage, and network traffic.

    However, we do provide the data from the web crawl and the results of running detectors (see Data). The analysis code described later runs on the preprocessed data included in this repository.

  • analysis/: Third-party age verification provider prevalence analysis (Section 3.1.2 and Section 4)

    • Includes code for:
      1. Generating result JSON files from crawl data
      2. Combining the JSON files into a CSV file (one per state)
      3. Computing stats and graphs from the processed data
    • Evaluators are expected to run only #3 which uses preprocessed results from steps 1 and 2.
  • control-webpage/: Code to run the control webpage (Control webpages under Section 3.1.2)

  • yoti-scm-re/: Yoti SICAP partially reverse-engineered code (Sections 5.3.1 and 5.5.3)

  • yoti-sicap-bypass/: Chrome extension that bypasses Yoti's age estimation method (Section 5.5.3)

Claims

  1. The data reported in Section 3.3 matches that computed from the data.

    Please see the corresponding section in analysis/prevalence.ipynb.

  2. The data reported in Section 4 matches that computed from the data.

    Please see the corresponding section in analysis/prevalence.ipynb.

  3. The figures in the ipynb are semantically equivalent to those in the paper.

    Please see the figures generated in analysis/prevalence.ipynb.

Data

We conducted our web crawls in August 2025 from a machine in Georgia and through two DigitalOcean VPSes in Texas and New York.

We make the data (rendered HTML content) from these crawls available under CC0. Note that these files are very large (~150 GiB compressed, ~750 GiB uncompressed).

For convenience, we include the (compressed) CSV files generated after running our detectors on the raw data in analysis/data. These are approximately 30 MiB compressed and 500 MiB uncompressed. The analysis code in our IPython notebooks and figure generation scripts reads and operates on these CSV files.

The API responses from the web classification API (see Section 3.1.4) are also included in analysis/data as klazify.tar.gz.

Age Verification Provider Prevalence (Section 4)

We provide the IPython notebook analysis/prevalence.ipynb that computes the statistics and figures used in our paper. We make an effort to structure this notebook to match the structure of the relevant sections of the paper.

  1. Install uv

  2. Run uv sync in analysis to set up a python environment (tested with python 3.12.11 on linux 6.12)

  3. Extract the .gz files in analysis/data

  4. Run prevalence.ipynb within the virtual environment created by uv

    This step takes approximately 15 minutes on a typical 2021 laptop.

Yoti (Section 5)

As noted in our paper, we share the partially reverse-engineered SICAP 2.6.2 JavaScript module. We also include a "pseudocode" version of this module, reconstructed based on our RE results.

Additionally, we include the source code for a proof-of-concept Chrome extension that bypasses Yoti's age estimation. We also used this scaffolding as part of our dynamic analysis.

Ethics

In the process of conducting our crawls, we sent the minimal amount of traffic necessary to the sites we crawled. During our reverse-engineering efforts, we sent no malicious or abnormal data to any external servers.

About

Artifact for 'Papers, Please: A First Look at Age Verification on the Web' (IEEE S&P 2026)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages