Skip to content

Commit 769c959

Browse files
authored
Serve security.txt (#8362)
1 parent 653d35b commit 769c959

File tree

5 files changed

+37
-0
lines changed

5 files changed

+37
-0
lines changed

app/lib/frontend/handlers/cache_control.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ final class CacheControl {
5555
public: true,
5656
);
5757

58+
/// `Cache-Control` headers for API end-points returning slowly changing content,
59+
/// without any hash in the URL.
60+
static const mostlyStaticApi = CacheControl(
61+
maxAge: Duration(hours: 8),
62+
public: true,
63+
);
64+
5865
/// `Cache-Control` headers for API end-points returning completion data for
5966
/// use in IDE integrations.
6067
static const completionData = CacheControl(

app/lib/frontend/handlers/misc.dart

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,21 @@ import 'cache_control.dart';
3131

3232
final _log = Logger('pub.handlers.misc');
3333

34+
/// Handles requests for /.well-known/security.txt
35+
Future<shelf.Response> wellKnownSecurityTxtHandler(
36+
shelf.Request request) async {
37+
final expiresDate =
38+
clock.now().add(Duration(days: 31)).toIso8601String().split('T').first;
39+
final content = 'Contact: https://goo.gl/vulnz\n'
40+
'Policy: https://pub.dev/security\n'
41+
'Preferred-Languages: en\n'
42+
'Expires: ${expiresDate}T00:00:00z\n';
43+
return shelf.Response.ok(
44+
content,
45+
headers: CacheControl.mostlyStaticApi.headers,
46+
);
47+
}
48+
3449
/// Handles requests for /help
3550
/// Handles requests for /help/<article>
3651
Future<shelf.Response> helpPageHandler(

app/lib/frontend/handlers/routes.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,11 @@ class PubSiteService {
309309
Future<Response> experimental(Request request) =>
310310
experimentalHandler(request);
311311

312+
/// Renders the /.well-known/security.txt page
313+
@Route.get('/.well-known/security.txt')
314+
Future<Response> wellKnownSecurityTxt(Request request) =>
315+
wellKnownSecurityTxtHandler(request);
316+
312317
// ****
313318
// **** Account, authentication and user administration
314319
// ****

app/lib/frontend/handlers/routes.g.dart

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/pub_integration/lib/script/public_pages.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class PublicPagesScript {
2828
await _atomFeed();
2929
await _searchPage();
3030
await _sitemaps();
31+
await _wellKnownFiles();
3132
await _customApis();
3233
await _badRequest();
3334
} finally {
@@ -81,6 +82,10 @@ class PublicPagesScript {
8182
await _pubClient.getContent('/sitemap-2.txt');
8283
}
8384

85+
Future<void> _wellKnownFiles() async {
86+
await _pubClient.getContent('/.well-known/security.txt');
87+
}
88+
8489
Future<void> _customApis() async {
8590
final packageNames = await _pubClient.apiPackageNames();
8691
if (!packageNames.contains('retry')) {

0 commit comments

Comments
 (0)