-
Notifications
You must be signed in to change notification settings - Fork 1
Add security improvements to the codebase #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,17 +1,38 @@ | ||
| package linkpreview | ||
|
|
||
| import ( | ||
| "errors" | ||
| "io" | ||
| "net/http" | ||
| "net/url" | ||
| "strings" | ||
|
|
||
| "github.com/PuerkitoBio/goquery" | ||
| ) | ||
|
|
||
| func validateURL(link string) error { | ||
| parsedURL, err := url.ParseRequestURI(link) | ||
| if err != nil || !strings.HasPrefix(parsedURL.Scheme, "http") { | ||
| return errors.New("invalid URL") | ||
| } | ||
| return nil | ||
| } | ||
|
|
||
| func Parse(link string, options ...ConfigOption) (ParserResult, error) { | ||
| if err := validateURL(link); err != nil { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe this is not necessary as |
||
| return ParserResult{}, err | ||
| } | ||
|
|
||
| request, err := http.NewRequest("GET", link, nil) | ||
| if err != nil { | ||
| return ParserResult{}, err | ||
| } | ||
|
|
||
| // Add security headers | ||
| request.Header.Set("X-Content-Type-Options", "nosniff") | ||
| request.Header.Set("X-Frame-Options", "DENY") | ||
| request.Header.Set("X-XSS-Protection", "1; mode=block") | ||
|
Comment on lines
+32
to
+34
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is incorrect usage of secure headers. They are for response headers only. |
||
|
|
||
| response, err := http.DefaultClient.Do(request) | ||
| if err != nil { | ||
| return ParserResult{}, err | ||
|
|
@@ -22,6 +43,10 @@ func Parse(link string, options ...ConfigOption) (ParserResult, error) { | |
| } | ||
|
|
||
| func ParseFromReader(link string, data io.Reader, options ...ConfigOption) (ParserResult, error) { | ||
| if err := validateURL(link); err != nil { | ||
| return ParserResult{}, err | ||
| } | ||
|
|
||
| doc, err := goquery.NewDocumentFromReader(data) | ||
| if err != nil { | ||
| return ParserResult{}, err | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,9 @@ | ||
| package linkpreview | ||
|
|
||
| import ( | ||
| "errors" | ||
| ) | ||
|
|
||
| func (ctx *ParserContext) Parse() error { | ||
| err := ctx.readAllTags() | ||
| if err != nil { | ||
|
|
@@ -52,6 +56,9 @@ func (ctx *ParserContext) readAllTags() error { | |
| metaTag.OtherAttrs[attr.Key] = attr.Val | ||
| } | ||
| } | ||
| if err := validateMetaTag(metaTag); err != nil { | ||
| return err | ||
| } | ||
| ctx.MetaTags = append(ctx.MetaTags, metaTag) | ||
| } | ||
|
|
||
|
|
@@ -76,6 +83,9 @@ func (ctx *ParserContext) readAllTags() error { | |
| linkTag.OtherAttrs[attr.Key] = attr.Val | ||
| } | ||
| } | ||
| if err := validateLinkTag(linkTag); err != nil { | ||
| return err | ||
| } | ||
| ctx.LinkTags = append(ctx.LinkTags, linkTag) | ||
| } | ||
|
|
||
|
|
@@ -95,3 +105,23 @@ func (ctx *ParserContext) parseBasicTags() { | |
| } | ||
| } | ||
| } | ||
|
|
||
| func validateMetaTag(tag *MetaTag) error { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. HTML content may be not correct 100%. The use of this function can cause error to be returned due to a single incorrect piece of data. I suggest adding a config item to ParserConfig, says |
||
| if tag.Name == "" && tag.Property == "" { | ||
| return errors.New("meta tag must have either a name or property attribute") | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is recommended not to use dynamic error. You should place this error in top of the file like: var (
errTagInvalid = errors.New("tag is invalid")
)
// In here
return fmt.Errorf("%w: meta tag must have either a name or property attribute", errTagInvalid)Another option is to make this function just return |
||
| } | ||
| if tag.Content == "" && tag.Value == "" { | ||
| return errors.New("meta tag must have either a content or value attribute") | ||
| } | ||
| return nil | ||
| } | ||
|
|
||
| func validateLinkTag(tag *LinkTag) error { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The same comment for this function. |
||
| if tag.Rel == "" { | ||
| return errors.New("link tag must have a rel attribute") | ||
| } | ||
| if tag.Href == "" { | ||
| return errors.New("link tag must have an href attribute") | ||
| } | ||
| return nil | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,18 +19,22 @@ func (ctx *ParserContext) parseMaybeFavicon(tag *LinkTag) *Image { | |
| return nil | ||
| } | ||
|
|
||
| if err := validateURL(tag.Href); err != nil { | ||
| return nil | ||
| } | ||
|
|
||
| image := &Image{ | ||
| URL: parseURL(tag.Href, ctx.Link), | ||
| Type: strOr(tag.Type, tag.Rel), | ||
| } | ||
|
|
||
| if tag.Sizes != "" { | ||
| wh := strings.Split(tag.Sizes, "x") | ||
| if len(wh) == 2 { | ||
| image.Width = parseInt(wh[0]) | ||
| image.Height = parseInt(wh[1]) | ||
| wh := strings.Split(tag.Sizes, "x") | ||
| if len(wh) == 2 { | ||
| image.Width = parseInt(wh[0]) | ||
| image.Height = parseInt(wh[1]) | ||
| } | ||
|
Comment on lines
+32
to
+36
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please restore indentation of this block. |
||
| } | ||
| } | ||
|
|
||
| return image | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please move this to
utils.go