diff --git a/.github/SECURITY.md b/.github/SECURITY.md
index 258451e..1798914 100644
--- a/.github/SECURITY.md
+++ b/.github/SECURITY.md
@@ -1,23 +1,54 @@
-# Reporting Vulnerabilities
+# Security policy
-**⚠️ Please do not file public GitHub issues for security vulnerabilities as they are open for everyone to see! ⚠️**
+pytest-env is a pytest plugin that sets environment variables for a test session from pytest configuration and `.env`
+files. This policy says how to report a security problem and how we decide whether a report is one.
-We encourage responsible disclosure practices for security vulnerabilities.
+## Reporting a vulnerability
-## Reporting a Vulnerability
+**Do not open a public issue for a security problem.** Use
+[GitHub's private vulnerability reporting](https://github.com/pytest-dev/pytest-env/security/advisories/new). If you do
+not have a GitHub account, or you are a Tidelift subscriber, report through the
+[Tidelift security contact](https://tidelift.com/security) instead; Tidelift coordinates the fix and the disclosure with
+us. If neither works for you, email [gaborjbernat@gmail.com](mailto:gaborjbernat@gmail.com).
-If you believe you've found a security-related bug, fill out a new vulnerability report via GitHub directly. To do so,
-follow these instructions:
+Include what the attacker controls and what they gain, the steps or a proof of concept, and the versions and platform
+you tested. Write the report yourself; unreviewed tool or model output takes longer to triage.
-1. Click on the `Security` tab in the project repository.
-1. Click the green `Report a vulnerability` button at the top right corner.
-1. Fill in the form as accurately as you can, including as many details as possible.
-1. Click the green `Submit report` button at the bottom.
+## What to expect
-## Don't have a GitHub account?
+Volunteers maintain pytest-env, with no on-call rotation. We aim to acknowledge a report within **5 working days** and
+assess it within **15 working days**. Fixes are developed in a private fork attached to the draft advisory, ship in a
+new release, and the advisory, with a CVE requested through GitHub, goes out with that release. The default embargo is
+**90 days** from the report; we agree any change with the reporter. We credit reporters in the advisory under the name
+they choose, or not at all. There is no bug bounty.
-Alternatively, to report a security vulnerability, please use the
-[Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure.
+## Supported versions
-It is currently set up to forward every incoming report to Bernát Gábor. We will try to assess the problem in timely
-manner and disclose it in a responsible way.
+Only the latest release receives fixes. Confirm the problem reproduces on it before reporting.
+
+## Vulnerability or bug
+
+A report is a vulnerability when an attacker who controls only an input that the [threat model](THREAT_MODEL.md) lists
+as untrusted breaks a guarantee pytest-env makes. A report that first needs control of something the threat model
+trusts, such as the pytest configuration or the `.env` files it names, is a bug: we fix it in the open and publish no
+advisory. Classify by who supplies the dangerous input, not by how bad the outcome sounds.
+
+**In scope**
+
+- pytest-env loading a `.env` file that neither the configuration nor `--envfile` names.
+- A variable value printed when `--pytest-env-verbose` is off.
+- TOML, INI and command-line precedence, or the skip-if-set baseline, differing from the documentation so a value the
+ user protected is overwritten.
+- A configured value creating or removing a variable other than the one its entry names.
+
+**Out of scope**
+
+- Values the configuration sets: the project's pytest configuration is trusted, like the `conftest.py` and tests it
+ runs.
+- `{VAR}` expansion reaching other variables: it is documented, off with `R:` in INI and opt-in with `transform` in
+ TOML.
+- `.env` paths the configuration or `--envfile` chooses, including ones outside the rootdir.
+- Values printed with `--pytest-env-verbose`, which exists to print them.
+- Parsing behavior of `.env` files, which belongs to python-dotenv.
+
+If you cannot tell which side a finding falls on, report it privately and we will decide.
diff --git a/.github/THREAT_MODEL.md b/.github/THREAT_MODEL.md
new file mode 100644
index 0000000..2afe894
--- /dev/null
+++ b/.github/THREAT_MODEL.md
@@ -0,0 +1,97 @@
+# Threat model
+
+This model says what pytest-env trusts, where untrusted input enters, and which guarantees hold at each boundary, so a
+report can be classified as a vulnerability or a bug. [SECURITY.md](SECURITY.md) covers reporting; if the two disagree,
+SECURITY.md wins and we fix this file.
+
+## How pytest-env works
+
+Before tests are collected, pytest-env reads its entries from the `[pytest_env]` table of `pytest.toml`, `.pytest.toml`
+or `pyproject.toml`, found in the pytest configuration's directory or the nearest parent with such a table, or else from
+the `env` option of the INI configuration. It loads the `.env` files that `env_files` or `--envfile` name, resolved
+against the rootdir and parsed with python-dotenv, then sets, unsets or keeps each variable, expanding `{VAR}`
+references in INI entries not marked `R:` and in TOML entries that set `transform`. With `--pytest-env-verbose` it
+prints each assignment, values included, in the report header.
+
+```mermaid
+flowchart LR
+ cfg[("pytest config
(trusted)")] --> pe["pytest-env"]
+ dot[(".env files named by config
(trusted)")] --> pe
+ pe -->|"set, unset, expand"| env["os.environ for the session"]
+ pe -->|"--pytest-env-verbose only"| log["Report header"]
+ classDef trusted fill:#cfe4ff,stroke:#1f6feb,color:#0b1f3a;
+ classDef boundary fill:#ffe3a3,stroke:#d29200,color:#3a2c00;
+ class cfg,dot,pe trusted;
+ class env,log boundary;
+```
+
+## Compared with similar tools
+
+We drew the boundary where comparable projects in other ecosystems draw theirs. The shared rule, stated by the
+[Node.js threat model](https://github.com/nodejs/node/blob/main/SECURITY.md#the-nodejs-threat-model), is that a report
+which first needs a trusted element compromised is out of scope; the first triage question, as
+[DOMPurify](https://github.com/cure53/DOMPurify/blob/main/SECURITY.md#what-we-consider-a-vulnerability) puts it, is what
+the attacker controls.
+
+| Project | Language | Where it draws the line |
+| -------------------------------------------------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| [direnv](https://direnv.net/man/direnv.1.html) | Go | Treats `.envrc` as untrusted until `direnv allow`, because it executes it; pytest-env's `.env` files are data named by trusted configuration and are never executed. |
+| [dotenv](https://github.com/motdotla/dotenv/security/policy) | JavaScript | Publishes only a reporting contact. |
+| [Vitest](https://github.com/vitest-dev/vitest/security/policy) | JavaScript | Trusts the developer, the config file, plugins and every project file; only reports that need no trusted element compromised count. |
+| [Jest](https://github.com/jestjs/jest/security/policy) | JavaScript | Test runner; private reports with an escalation path, and no separate threat model. |
+
+## Trusted
+
+An attacker who controls any of these already has what pytest-env could give them:
+
+- The pytest configuration and command line, including `env`, `env_files` and `--envfile`.
+- The `.env` files they name, and the process environment used for `{VAR}` expansion.
+- The tests, which run with the variables set.
+
+## Untrusted inputs
+
+| Input | Comes from | What pytest-env guarantees |
+| ------------------------- | --------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
+| Variable values in output | Secrets placed in `.env` files or the configuration | Not printed unless `--pytest-env-verbose` is given. |
+| `.env` names | Configuration and `--envfile` | Resolved against the rootdir and never searched for elsewhere; a missing `--envfile` raises, a missing configured file is skipped. |
+
+## Threats and controls
+
+| STRIDE | Threat | Control |
+| ---------------------- | ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Information disclosure | A secret from `.env` appears in a public CI log. | Values are printed only with `--pytest-env-verbose`. |
+| Tampering | A `.env` file nobody named is loaded. | Only named files are loaded. |
+| Tampering | A protected variable is overwritten. | `env_files_skip_if_set` takes its baseline before any `.env` file is applied; `D:` and `skip_if_set` entries check the environment at their place in the list. |
+
+## Release chain
+
+Releases run on the shared [tox-dev/github-workflows](https://github.com/tox-dev/github-workflows) pipeline. A release
+App, not a person, pushes the release commit and tag; the build installs its tools from a hash-checked `pylock.toml`
+resolved with a seven-day upload cooldown by default; PyPI receives the files through
+[trusted publishing](https://docs.pypi.org/trusted-publishers/) with attestations, and the GitHub Release is immutable.
+Every workflow pins third-party actions to a commit SHA.
+
+## Vulnerability or bug
+
+| Report | Verdict | Why |
+| --------------------------------------------------------------------- | ------------------- | ----------------------------- |
+| A secret shows up in the report header without `--pytest-env-verbose` | Vulnerability | Output guarantee broken. |
+| The INI entry `FOO={HOME}` expands to the home directory | Not a vulnerability | Documented expansion. |
+| A malicious `pytest.ini` sets `LD_PRELOAD` | Not a vulnerability | The configuration is trusted. |
+
+## Severity
+
+- **High:** a secret value printed without `--pytest-env-verbose`.
+- **Medium:** an unnamed `.env` file loaded, or a protected variable overwritten against the documented precedence.
+- **Low:** a crash or confusing error on malformed configuration.
+
+## Accepted risks
+
+- `--pytest-env-verbose` prints values, secrets included; do not enable it with secrets in public logs.
+- The TOML search walks up parent directories without checking who owns them; do not run pytest below a directory other
+ users can write.
+
+## Keeping this current
+
+Revisit this model when pytest-env gains a new input source, network access, a new way to run code, or a new place it
+writes to, and whenever an advisory is published.