Unverified Commit cd5816c4 authored by memoclaw's avatar memoclaw Committed by GitHub

feat: add --allow-private-webhooks flag to bypass SSRF protection (#5694)

Co-authored-by: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent 851e090f
......@@ -15,6 +15,7 @@ import (
"github.com/usememos/memos/internal/profile"
"github.com/usememos/memos/internal/version"
"github.com/usememos/memos/plugin/webhook"
"github.com/usememos/memos/server"
"github.com/usememos/memos/store"
"github.com/usememos/memos/store/db"
......@@ -36,6 +37,7 @@ var (
InstanceURL: viper.GetString("instance-url"),
}
instanceProfile.Version = version.GetCurrentVersion()
webhook.AllowPrivateIPs = viper.GetBool("allow-private-webhooks")
if err := instanceProfile.Validate(); err != nil {
slog.Error("failed to validate profile", "error", err)
......@@ -105,6 +107,7 @@ func init() {
rootCmd.PersistentFlags().String("driver", "sqlite", "database driver")
rootCmd.PersistentFlags().String("dsn", "", "database source name(aka. DSN)")
rootCmd.PersistentFlags().String("instance-url", "", "the url of your memos instance")
rootCmd.PersistentFlags().Bool("allow-private-webhooks", false, "allow webhook URLs to resolve to private/reserved IP addresses")
if err := viper.BindPFlag("demo", rootCmd.PersistentFlags().Lookup("demo")); err != nil {
panic(err)
......@@ -130,6 +133,9 @@ func init() {
if err := viper.BindPFlag("instance-url", rootCmd.PersistentFlags().Lookup("instance-url")); err != nil {
panic(err)
}
if err := viper.BindPFlag("allow-private-webhooks", rootCmd.PersistentFlags().Lookup("allow-private-webhooks")); err != nil {
panic(err)
}
viper.SetEnvPrefix("memos")
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
......
......@@ -35,8 +35,16 @@ func init() {
}
}
// AllowPrivateIPs controls whether webhook URLs may resolve to reserved/private
// IP addresses. When true, the SSRF protection is disabled. This is useful for
// self-hosted deployments where webhooks target services on the local network.
var AllowPrivateIPs bool
// isReservedIP reports whether ip falls within any reserved/private range.
func isReservedIP(ip net.IP) bool {
if AllowPrivateIPs {
return false
}
for _, network := range reservedNetworks {
if network.Contains(ip) {
return true
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment