Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@startup-api/cloudflare",
"version": "0.4.1",
"version": "0.4.2",
"license": "Apache-2.0",
"publishConfig": {
"access": "public"
Expand Down
10 changes: 6 additions & 4 deletions src/auth/AtprotoProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -304,10 +304,12 @@ export class AtprotoProvider extends OAuthProvider {
status,
headers: {
'Content-Type': 'text/html; charset=utf-8',
// Same hardening as the auth error page: only same-origin styles/form, never framed, never cached
// (the re-rendered form reflects the user-supplied handle).
'Content-Security-Policy':
"default-src 'none'; style-src 'self' 'unsafe-inline'; form-action 'self'; base-uri 'none'; frame-ancestors 'none'",
// Hardening: same-origin styles only, never framed, never cached (the form reflects the
// user-supplied handle). NOTE: deliberately NO `form-action` directive — submitting this form
// hits our endpoint, which 302-redirects to the user's *own* authorization server (any PDS).
// `form-action` is enforced across the whole redirect chain, so `'self'` (or any fixed list)
// would block that cross-origin redirect and the login would silently fail.
'Content-Security-Policy': "default-src 'none'; style-src 'self' 'unsafe-inline'; base-uri 'none'; frame-ancestors 'none'",
'X-Content-Type-Options': 'nosniff',
'Referrer-Policy': 'no-referrer',
'Cache-Control': 'no-store',
Expand Down
3 changes: 3 additions & 0 deletions test/atproto.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ describe('atproto provider', () => {
// Auth page hardening: not framable, not cached (it can reflect the user's handle).
expect(res.headers.get('Content-Security-Policy')).toContain("frame-ancestors 'none'");
expect(res.headers.get('Cache-Control')).toBe('no-store');
// Must NOT set form-action: submitting this form 302-redirects to the user's own auth server
// (any PDS), and form-action is enforced across the redirect chain — restricting it breaks login.
expect(res.headers.get('Content-Security-Policy')).not.toContain('form-action');
const html = await res.text();
expect(html).toContain('name="handle"');
});
Expand Down