I think there is a few things here that could be decoupled:
- staging vs. cooldown
- staging vs. quarantinee
- staging as gatekeeping
- now or later
I’m not familiar with the details PEP 694, so please excuse me if I redefine things already decided there. From my perspective as a user, maintainer, and scanner/reporter:
at. 1: I belive staging should be index-level feature, while cooldown installer-level. I’d welcome default cooldown periods, but I don’t belive we should try to fix index-level security via it. Cooldown should be in a strong control of the user and let them adjust it to the risk model.
at. 2. I find staging as a maintainer-controlled feature that has also security implications. As a scanner, I definietly support triggering scans during the stage phase. For that, I need a) information about the staged uploads, b) some metadata. The usage of the staging should, however, be in the hands of the maintainer.
at. 3. Ideologically, I welcome the gatekeeping idea. Practically, I don’t belive we can in general hotfix it into legacy API. While the staging can act as index-enforced gatekeeping, I’d dear to ask: do we have scanners that will be able to leverage this right now? What would be the outcome of forced gatekeeping at the moment? From my perspective: having 30 minutes window to scan before package is publish would stop some repeating abuses by new packages - but they already live 3-10 minutes. To stop most of the malware, in my opinion, we would have to introduce hours-long window, the best 24h. However, I think we could introduce a middle-ground: opt-in staged releases for existing projects and opt-out for new projects. Allowing enforcing manual approvals from maintainers would also be a good security measure for projects that cannot benefit from trusted publishing and CI-level manual approvals.
at. 4. I definietly belive we could and should introduce first staging version now, in a simplified version. I’d advertise it as experimental feature, suggest collecting experience, and build the capacity for better implementation with PEP 694.
Answering some of initial questions from my perspective:
is “hide it from the canonical index until an async gate clears” the right minimal core?
I belive users should be able to install the package during the staging/gatekeeping, assuming they explicitly allow it. It could be achieved two ways: 1) publish staging information in index API and let installers decide, 2) provide link to the installable release file.
I’m not a fan of introducing - right now - gatekeeping as private-only scan feature. I don’t know how exactly the structure of reporters looks like at the moment, but I’d be afraid keeping access behind closed doors could actually delay the detection. I’d like the first staging or gatekeeping to be, if any, a minimal feature that keep the release away from regular users, but still let it use when explicitly enabled - similar to how already mentioned yanked or archived versions work, but more strict (e.g. I would suggest installer to have something like a flag --allow-staging=).
My suggestion would be to add “staged” field or endpoint/parameter in the existing Index API, with all necessary informations (or at least release files data) and separated RSS feed. I’d also introduce it as a release-level status, something that quarantinee is lacking at the moment. I think it would be relative small change comparing to providing separate private access. Based on experience, we could then introduce or not the gatekeeping with the bigger change.
how much of the verdict-reporting channel is worth standardizing now vs. leaving to 694?
The reporting API I’m aware of lacks some features, but I belive the biggest win would be to introduce staged releases and treat reports the same way as for live releases vs. trying to standardize the reporting (and, I assume, onboard more scanners so it would make sense). I’d rather leave standardazing API for the next step, maybe even experiment more with what could be collected and what would be helpful.
Should any version that is flagged by these scans trigger alerts to the project owner that it was rejected? What is the approach that would be the most comfortable for handling any potential false positives on scanning and rejection?
The last is actually the most important question. As I already mentioned, I’m able to stop repeating abuses timely, but anything less common requires manual verification. I don’t collect good statistics, but generally from ~200 alerts daily I produce 5-10 actual reports. I still have a limited scanning scope, and I hope there are people with more efficient systems, but I belive we have to be caution. And I don’t think we will benefit the most from forcing gatekeeping at the moment. Answering the notifications: I’d start with following the current process - put in quarantinee, let @miketheman verify and maintainers ask for details if they want to.
To sum up, I’d suggest:
a) opt-in staging releases allowing enforcing manual approval in PyPI by the maintainer,
b) having staging as a release-level state and exposing it separately in the Index API, so installers won’t see it by default,
c) issuing new PyPI tokens with a default expiry date (I know you can add it manually thanks to macaroons, but how many people do it?),
d) opt-out staging releases for new packages - and let disable it only after the first upload (maybe even after first 30 minutes?).
I see a) as the security mechanism for existing packages without breaking anything as it’s opt-in. The b) is in my opinion the cheaper way to start and we would benefit enough from it, leaving the entirely private staging/gatekeeping for the future. c) would be the simple, forward-thinking feature for the token usage, which will always be present, but we would enforce some control over the risk. It won’t fix nor break existing tokens, but we could teach people that tokens are time-constraind now. The d) is in my opinion a way to popularize staging, teach about possible gateway in the future and introduce some security review window with minimal inconvinience* for existing users. While the most damaging is malware via hacked access and poisoned releases, the most common is malware introduced in new packages. Adding an opt-out staging for new packages, maybe even true gatekeeping for first 30 minutes or so, could give as a way to make abusing PyPI less convinient.
*I’m aware of at least one user who publish relative many packages and it might affect them. Perhaps a per-user feature flag, so a specific user could be excluded from default staging on a request, would be helpful?