docs: Add 1 and update 6 files
All checks were successful
Build-Test-Publish / build (linux/amd64) (push) Successful in 1m25s
Build-Test-Publish / build (linux/arm64) (push) Successful in 2m21s
Build-Test-Publish / create-manifest (push) Successful in 15s

This commit is contained in:
Your Name
2025-08-10 22:50:51 +12:00
parent e64fbee94f
commit 22d4af7ac8
7 changed files with 203 additions and 11 deletions

View File

@@ -199,6 +199,7 @@ void Server::setup_routes() {
void Server::handle_cors_preflight(const drogon::HttpRequestPtr& req, std::function<void(const drogon::HttpResponsePtr &)>&& callback) {
auto resp = drogon::HttpResponse::newHttpResponse();
add_cors_headers(req, resp);
add_security_headers(resp);
resp->setStatusCode(drogon::k204NoContent);
callback(resp);
}
@@ -240,6 +241,33 @@ void Server::add_cors_headers(const drogon::HttpRequestPtr& req, const drogon::H
}
}
void Server::add_security_headers(const drogon::HttpResponsePtr& res) {
// Add security headers to prevent common web vulnerabilities
// Prevent clickjacking attacks
res->addHeader("X-Frame-Options", "DENY");
// Prevent MIME type sniffing
res->addHeader("X-Content-Type-Options", "nosniff");
// Enable XSS filter in browsers (legacy, but still useful for older browsers)
res->addHeader("X-XSS-Protection", "1; mode=block");
// Enforce HTTPS (only add if we're sure the server uses HTTPS)
// Note: Commented out by default as it requires HTTPS to be configured
// res->addHeader("Strict-Transport-Security", "max-age=31536000; includeSubDomains");
// Content Security Policy - restrictive by default
// This prevents loading of external resources and inline scripts
res->addHeader("Content-Security-Policy", "default-src 'self'; script-src 'none'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'");
// Referrer Policy - don't leak referrer information
res->addHeader("Referrer-Policy", "strict-origin-when-cross-origin");
// Permissions Policy (formerly Feature Policy) - disable unnecessary browser features
res->addHeader("Permissions-Policy", "geolocation=(), microphone=(), camera=(), payment=(), usb=(), magnetometer=(), gyroscope=(), accelerometer=()");
}
std::string Server::join(const std::vector<std::string>& strings, const std::string& delimiter) {
if (strings.empty()) return "";
@@ -261,6 +289,7 @@ void Server::handle_get_object(const drogon::HttpRequestPtr& req, std::function<
nlohmann::json response = {{"result", "error"}, {"error", "Couldn't find: " + key}};
resp->setBody(response.dump());
resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);
add_security_headers(resp);
callback(resp);
return;
}
@@ -273,12 +302,14 @@ void Server::handle_get_object(const drogon::HttpRequestPtr& req, std::function<
nlohmann::json response = {{"result", "error"}, {"error", "Hash recognised, but object missing for: " + entry.hash}};
resp->setBody(response.dump());
resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);
add_security_headers(resp);
callback(resp);
return;
}
// Send file
auto resp = drogon::HttpResponse::newFileResponse(file_path.string());
add_security_headers(resp);
callback(resp);
}
@@ -292,6 +323,7 @@ void Server::handle_get_hash(const drogon::HttpRequestPtr& req, std::function<vo
nlohmann::json response = {{"result", "error"}, {"error", "Label:tag not found"}};
resp->setBody(response.dump());
resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);
add_security_headers(resp);
callback(resp);
return;
}
@@ -300,6 +332,7 @@ void Server::handle_get_hash(const drogon::HttpRequestPtr& req, std::function<vo
nlohmann::json response = {{"result", "success"}, {"hash", entry.hash}};
resp->setBody(response.dump());
resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);
add_security_headers(resp);
callback(resp);
}
@@ -312,6 +345,7 @@ void Server::handle_get_directory(const drogon::HttpRequestPtr& /*req*/, std::fu
nlohmann::json response = {{"result", "error"}, {"error", "Failed to retrieve directory listing"}};
resp->setBody(response.dump());
resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);
add_security_headers(resp);
callback(resp);
return;
}
@@ -326,6 +360,7 @@ void Server::handle_get_directory(const drogon::HttpRequestPtr& /*req*/, std::fu
nlohmann::json response = {{"result", "success"}, {"entries", entries_array}};
resp->setBody(response.dump());
resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);
add_security_headers(resp);
callback(resp);
}
@@ -356,6 +391,7 @@ void Server::handle_get_metadata(const drogon::HttpRequestPtr& req, std::functio
resp->setBody(response.dump());
}
resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);
add_security_headers(resp);
callback(resp);
}
@@ -374,6 +410,7 @@ void Server::handle_delete_object(const drogon::HttpRequestPtr& req, std::functi
{
std::map<std::string, std::string> params;
if (!validate_write_request(req, resp, {"hash"}, params)) {
add_security_headers(resp);
callback(resp);
return;
}
@@ -394,6 +431,7 @@ void Server::handle_delete_object(const drogon::HttpRequestPtr& req, std::functi
nlohmann::json response = {{"result", "error"}, {"error", "Failed to remove some or all associated tags"}};
resp->setBody(response.dump());
resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);
add_security_headers(resp);
callback(resp);
return;
}
@@ -417,6 +455,7 @@ void Server::handle_delete_object(const drogon::HttpRequestPtr& req, std::functi
nlohmann::json response = {{"result", "success"}};
resp->setBody(response.dump());
resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);
add_security_headers(resp);
callback(resp);
}
@@ -431,6 +470,7 @@ void Server::handle_exists(const drogon::HttpRequestPtr& req, std::function<void
auto resp = drogon::HttpResponse::newHttpResponse();
resp->setBody(response.dump());
resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);
add_security_headers(resp);
callback(resp);
}
@@ -448,6 +488,7 @@ void Server::handle_get_version(const drogon::HttpRequestPtr& req, std::function
nlohmann::json response = {{"result", "failed"}, {"error", "Failed to get version for: " + key}};
resp->setBody(response.dump());
resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);
add_security_headers(resp);
callback(resp);
return;
}
@@ -460,6 +501,7 @@ void Server::handle_get_version(const drogon::HttpRequestPtr& req, std::function
}
resp->setBody(response.dump());
resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);
add_security_headers(resp);
callback(resp);
}