Commit Graph
362 Commits
Author SHA1 Message Date
Dmitry VerkhoturovandGitHub ba7c3aed94 refactor: modernise Go code with go fix and manual improvements (#2027)
Apply go fix ./... analysers (Go 1.26) across backend and examples:
- interface{} → any (type alias, no behaviour change)
- for i := 0; i < N; i++ → for range N / for i := range N
- slices.Contains / slices.ContainsFunc replacing manual loops
- strings.SplitSeq replacing strings.Split in range (avoids allocation)
- strings.CutPrefix replacing HasPrefix+TrimPrefix
- min() replacing manual if/else
- fmt.Appendf replacing []byte(fmt.Sprintf(...))
- strings.Builder replacing string += concatenation
- wg.Go(func(){}) replacing wg.Add(1)/go/wg.Done() pattern
- removed redundant ii := i loop variable copies (unnecessary since Go 1.22)

omitempty on struct-typed JSON fields: go fix removed omitempty from
struct-typed fields (time.Time, PostInfo, UserDetailEntry) because
encoding/json's omitempty never applied to struct types — it was always
a no-op. Kept as bare tags (no omitzero replacement) to preserve the
existing serialisation behaviour.
2026-03-25 16:42:37 -05:00
Umputun aca0cff399 fix: IPv6 address truncation and image proxy SSRF vulnerabilities
Replace strings.Split(RemoteAddr, ":") with net.SplitHostPort for correct
IPv6 address extraction in vote deduplication and comment IP tracking.

Harden image proxy: add SSRF-safe transport blocking private/reserved IPs
at connection time with DNS rebinding protection, sanitize error messages
to prevent information leakage, add response size limit via io.LimitReader.

Fix shadowed error variables in BlockedUsers, SetTitle, and Delete methods.
Exclude gosec taint analysis false positives at linter config level.
2026-02-28 04:13:07 -06:00
Dmitry VerkhoturovandUmputun 78d6de6bce Add X-Content-Type-Options and Referrer-Policy security headers
Add two missing security headers to the existing securityHeadersMiddleware:

- X-Content-Type-Options: nosniff — prevents browsers from MIME-sniffing
  responses away from the declared Content-Type, stopping e.g. a
  user-uploaded image from being reinterpreted as executable HTML/JS

- Referrer-Policy: strict-origin-when-cross-origin — limits URL information
  leaked in the Referer header on cross-origin requests to just the origin
  (no path), and sends nothing at all on HTTPS-to-HTTP downgrades
2026-02-21 20:14:44 -06:00
Dmitry VerkhoturovandUmputun d5b07d7670 Fix WriteHeader + RenderJSON causing wrong Content-Type header
Replace WriteHeader() + RenderJSON() pattern with EncodeJSON() which
properly sets Content-Type header before writing status code. The
previous pattern caused Content-Type to default to text/plain instead
of application/json, breaking frontend JSON parsing.

Fixes #1979
2025-12-16 13:01:19 -06:00
Dmitry VerkhoturovandUmputun bc612ddf81 Remove redundant frame ancestors log from middleware
The log message was printed on every request when allowed ancestors
were configured, creating unnecessary noise in the logs.
2025-12-04 11:15:06 -06:00
Dmitry VerkhoturovandUmputun 658bf307b1 Add mailto: to CSP frame-src directive
Allow mailto links on the deleteme page to work without being blocked
by Content Security Policy.
2025-12-04 11:13:50 -06:00
Dmitry VerkhoturovandGitHub 564e8ff316 Update go dependencies (#1972) 2025-12-03 19:47:01 -06:00
dependabot[bot]andUmputun 6d8a0c783b Bump the go-modules-updates group across 1 directory with 11 updates
Bumps the go-modules-updates group with 11 updates in the /backend directory:

| Package | From | To |
| --- | --- | --- |
| [github.com/PuerkitoBio/goquery](https://github.com/PuerkitoBio/goquery) | `1.10.2` | `1.11.0` |
| [github.com/alecthomas/chroma/v2](https://github.com/alecthomas/chroma) | `2.15.0` | `2.20.0` |
| [github.com/go-chi/chi/v5](https://github.com/go-chi/chi) | `5.2.1` | `5.2.3` |
| [github.com/go-chi/cors](https://github.com/go-chi/cors) | `1.2.1` | `1.2.2` |
| [github.com/go-pkgz/jrpc](https://github.com/go-pkgz/jrpc) | `0.3.1` | `0.4.0` |
| [github.com/go-pkgz/lgr](https://github.com/go-pkgz/lgr) | `0.12.0` | `0.12.1` |
| [github.com/go-pkgz/rest](https://github.com/go-pkgz/rest) | `1.20.3` | `1.20.4` |
| [github.com/golang-jwt/jwt/v5](https://github.com/golang-jwt/jwt) | `5.2.2` | `5.3.0` |
| [github.com/stretchr/testify](https://github.com/stretchr/testify) | `1.10.0` | `1.11.1` |
| [go.etcd.io/bbolt](https://github.com/etcd-io/bbolt) | `1.4.0` | `1.4.3` |
| [golang.org/x/image](https://github.com/golang/image) | `0.26.0` | `0.33.0` |

Updates `github.com/PuerkitoBio/goquery` from 1.10.2 to 1.11.0
- [Release notes](https://github.com/PuerkitoBio/goquery/releases)
- [Commits](https://github.com/PuerkitoBio/goquery/compare/v1.10.2...v1.11.0)

Updates `github.com/alecthomas/chroma/v2` from 2.15.0 to 2.20.0
- [Release notes](https://github.com/alecthomas/chroma/releases)
- [Commits](https://github.com/alecthomas/chroma/compare/v2.15.0...v2.20.0)

Updates `github.com/go-chi/chi/v5` from 5.2.1 to 5.2.3
- [Release notes](https://github.com/go-chi/chi/releases)
- [Changelog](https://github.com/go-chi/chi/blob/master/CHANGELOG.md)
- [Commits](https://github.com/go-chi/chi/compare/v5.2.1...v5.2.3)

Updates `github.com/go-chi/cors` from 1.2.1 to 1.2.2
- [Release notes](https://github.com/go-chi/cors/releases)
- [Commits](https://github.com/go-chi/cors/compare/v1.2.1...v1.2.2)

Updates `github.com/go-pkgz/jrpc` from 0.3.1 to 0.4.0
- [Release notes](https://github.com/go-pkgz/jrpc/releases)
- [Commits](https://github.com/go-pkgz/jrpc/compare/v0.3.1...v0.4.0)

Updates `github.com/go-pkgz/lgr` from 0.12.0 to 0.12.1
- [Release notes](https://github.com/go-pkgz/lgr/releases)
- [Commits](https://github.com/go-pkgz/lgr/compare/v0.12.0...v0.12.1)

Updates `github.com/go-pkgz/rest` from 1.20.3 to 1.20.4
- [Release notes](https://github.com/go-pkgz/rest/releases)
- [Commits](https://github.com/go-pkgz/rest/compare/v1.20.3...v1.20.4)

Updates `github.com/golang-jwt/jwt/v5` from 5.2.2 to 5.3.0
- [Release notes](https://github.com/golang-jwt/jwt/releases)
- [Commits](https://github.com/golang-jwt/jwt/compare/v5.2.2...v5.3.0)

Updates `github.com/stretchr/testify` from 1.10.0 to 1.11.1
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.10.0...v1.11.1)

Updates `go.etcd.io/bbolt` from 1.4.0 to 1.4.3
- [Release notes](https://github.com/etcd-io/bbolt/releases)
- [Commits](https://github.com/etcd-io/bbolt/compare/v1.4.0...v1.4.3)

Updates `golang.org/x/image` from 0.26.0 to 0.33.0
- [Commits](https://github.com/golang/image/compare/v0.26.0...v0.33.0)

---
updated-dependencies:
- dependency-name: github.com/PuerkitoBio/goquery
  dependency-version: 1.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-modules-updates
- dependency-name: github.com/alecthomas/chroma/v2
  dependency-version: 2.20.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-modules-updates
- dependency-name: github.com/go-chi/chi/v5
  dependency-version: 5.2.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-modules-updates
- dependency-name: github.com/go-chi/cors
  dependency-version: 1.2.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-modules-updates
- dependency-name: github.com/go-pkgz/jrpc
  dependency-version: 0.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-modules-updates
- dependency-name: github.com/go-pkgz/lgr
  dependency-version: 0.12.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-modules-updates
- dependency-name: github.com/go-pkgz/rest
  dependency-version: 1.20.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-modules-updates
- dependency-name: github.com/golang-jwt/jwt/v5
  dependency-version: 5.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-modules-updates
- dependency-name: github.com/stretchr/testify
  dependency-version: 1.11.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-modules-updates
- dependency-name: go.etcd.io/bbolt
  dependency-version: 1.4.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-modules-updates
- dependency-name: golang.org/x/image
  dependency-version: 0.33.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-modules-updates
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-03 18:17:46 -06:00
Dmitry VerkhoturovandGitHub baf0db1947 Get rid of github.com/go-chi/render use (#1919)
Replace go-chi/render with go-pkgz/rest for JSON responses and custom
helpers for HTML/plain text responses.

Key changes:
- Replace render.JSON/render.Status with rest.RenderJSON and explicit
  w.WriteHeader() calls
- Replace render.DecodeJSON with json.NewDecoder().Decode()
- Add SendErrorJSON helper that sets Content-Type header before
  WriteHeader (required since rest.RenderJSON can't set headers after
  WriteHeader is called)
- Add HTMLResponse and PlainTextResponse helpers

Fix export double-execution in migrator.go:
The original code called Export twice - once to io.Discard to check for
errors, then again to actually write. This was wasteful and had a race
condition risk. Now file mode buffers to memory first for atomic
success/failure, while stream mode writes directly with proper error
handling.
2025-12-03 11:41:29 -06:00
Dmitry Verkhoturov edfc5b9d76 Automatic fix of errors reported by golangci-lint v2
- Use strings.ReplaceAll
- Remove redundant internal structure names
2025-03-24 22:46:43 +01:00
Dmitry Verkhoturov 82a0888c42 add pagination to GET /api/v1/find endpoint
`format=tree` pagination provides top-level comments with all replies
and returns the last top-level comment as `last_comment` to be used
as `offset` for the next page. If comments and replies overflow
the limit, the one stepping out of the limit will not be returned.
 If the first comment and its replies after the given offset overflow
 the limit, it will be returned with all the replies.

`format=plain` pagination works by providing all comments and returning
the last comment as `last_comment` to be used as `offset`
for the next page.
2024-12-10 14:26:55 +00:00
Dmitry Verkhoturov e61a46efff Improve error message for checking claims.Audience 2024-12-10 00:45:04 +00:00
Dmitry Verkhoturov f473105c52 add tests for jwt5 multiple auds and improve existing tests 2024-12-09 01:54:04 +00:00
Dmitry Verkhoturov e3ad01b555 migrate to go-pkgz/auth/v2 2024-12-09 01:54:03 +00:00
Dmitry Verkhoturov 8d9e55c33c update github.com/golang-jwt/jwt to v5 2024-12-09 01:54:03 +00:00
Dmitry Verkhoturov 4ed48dd85c Improve tests 2024-12-09 01:45:57 +00:00
Dmitry VerkhoturovandUmputun 7604548035 Update go to 1.23, golangci-lint to 1.61, baseimage to 1.14 2024-11-08 16:19:58 -06:00
Dmitry VerkhoturovandUmputun 6140d82eb2 Fix CSP img-src directive to allow everything without proxy
Change the default img-src value to "*" and sets it to "'self'" when
image proxy is enabled. The previous state was inversion of this logic
which was wrong.
2024-10-20 15:55:51 -05:00
Dmitry VerkhoturovandUmputun f9d4837567 Add Content-Security-Policy and Permissions-Policy headers
`Content-Security-Policy` now restricts resource loading and execution
to enhance security:
  - `default-src 'none'`: Disallow all resource loading by default.
  - `base-uri 'none'`: Prevents the use of `<base>` tag to change the
  base URL for relative URLs.
  - `form-action 'none'`: Disallows form submissions.
  - `connect-src 'self'`: Restricts the origins that can be connected to
   (via XHR, WebSockets, etc.) to the same origin.
  - `frame-src 'self'`: Restricts the origins that can be embedded using
   `<frame>` and `<iframe>` to the same origin (for `/web/` demo
    endpoint).
  - `frame-ancestors %s;`: Specifies the origins that are allowed to
  embed this content in a frame. If no specific origins are allowed, it
  defaults to `*` (any origin). This enhances security by controlling
  which sites can embed your content.
  - `img-src 'self'`: Allows images to be loaded only from the same
  origin. If `imageProxyEnabled` is true, allows images from any origin
  (`*`).
  - `script-src 'self' 'unsafe-inline'`: Allows scripts to be loaded and
   executed only from the same origin and allows inline scripts.
  - `style-src 'self' 'unsafe-inline'`: Allows styles to be loaded and
  applied only from the same origin and allows inline styles.
  - `font-src data:`: Allows fonts to be loaded from data URIs.
  - `object-src 'none'`: Disallows the use of `<object>`, `<embed>`, and
   `<applet>` tags.

`Permissions-Policy` now restricts the use of certain browser features
which we don't use to enhance user privacy and security:
  - `accelerometer=()`: Disables the use of the accelerometer sensor.
  - `autoplay=()`: Disables automatic playback of media.
  - `camera=()`: Disables the use of the camera.
  - `cross-origin-isolated=()`: Disallows the page from being treated as
   cross-origin isolated.
  - `display-capture=()`: Disables the ability to capture the display.
  - `encrypted-media=()`: Disables the use of Encrypted Media Extensions
  .
  - `fullscreen=()`: Disables the ability to use fullscreen mode.
  - `geolocation=()`: Disables the use of geolocation.
  - `gyroscope=()`: Disables the use of the gyroscope sensor.
  - `keyboard-map=()`: Disables the use of the keyboard map.
  - `magnetometer=()`: Disables the use of the magnetometer sensor.
  - `microphone=()`: Disables the use of the microphone.
  - `midi=()`: Disables the use of the MIDI API.
  - `payment=()`: Disables the Payment Request API.
  - `picture-in-picture=()`: Disables the use of Picture-in-Picture mode
  .
  - `publickey-credentials-get=()`: Disables the use of the Web
  Authentication API.
  - `screen-wake-lock=()`: Disables the ability to prevent the screen
  from dimming.
  - `sync-xhr=()`: Disables synchronous XMLHttpRequest.
  - `usb=()`: Disables the use of the USB API.
  - `xr-spatial-tracking=()`: Disables the use of spatial tracking in
  WebXR.
  - `clipboard-read=()`: Disables the ability to read from the clipboard
  .
  - `clipboard-write=()`: Disables the ability to write to the clipboard
  .
  - `gamepad=()`: Disables the use of the Gamepad API.
  - `hid=()`: Disables the use of the Human Interface Device API.
  - `idle-detection=()`: Disables the ability to detect idle state.
  - `interest-cohort=()`: Disables the use of interest cohort tracking.
  - `serial=()`: Disables the use of the Serial API.
  - `unload=()`: Disables the ability to use the `beforeunload` and
  `unload` events.
  - `window-management=()`: Disables the ability to use window
  management APIs.
2024-10-15 17:53:12 -05:00
Umputun 8df986e70a Add content type check for images endpoint
A check in image proxy for validating content type of requested images added. Modified the related tests to accommodate these changes.
2024-07-01 14:47:25 -05:00
Dmitry VerkhoturovandUmputun e5743185b0 collect /find Info for tree and plain types consistently
MakeTree calculated Info locally for historical reasons,
and the results were consistent with the dataService.Info call
but calculated differently.

That change fixes that, ensuring that Info is requested
in the same manner.
2024-03-16 12:49:45 -05:00
Dmitry VerkhoturovandUmputun 01837b69e5 fix readonly status, deleted count for plain /find request 2024-03-04 15:44:19 -06:00
Dmitry VerkhoturovandUmputun 6269c19881 add more tests for GET /find endpoint 2024-02-21 10:43:28 -06:00
Dmitry VerkhoturovandUmputun 1313dee829 update to lcw v2 with generic types 2024-02-20 14:15:35 -06:00
Dmitry VerkhoturovandUmputun 532573fb34 fix problems reported by golangci-lint 2024-02-20 12:10:39 -06:00
Dmitry VerkhoturovandUmputun 0050c65596 add meaningful error for lack of auth on import, remap and backup
Previously, the error printed was just the following:

error response "401 Unauthorized", Unauthorized"

New error:

error response "401 Unauthorized", ensure you have set ADMIN_PASSWD
and provided it to the command you're running: Unauthorized
2024-01-28 12:16:24 -06:00
Dmitry VerkhoturovandUmputun 02db7a917d fix lack of error on file site export
Previously, status 200 was set for file export, which is used
for backup, which resulted in an inability to set an error status code
in case of a problem with file generation.

After this change, status code 200 would be written automatically by Go
before we start writing the response's body.
2024-01-28 12:16:24 -06:00
Dmitry VerkhoturovandUmputun cbd73865bd update go modules, update go-pkgz/auth to latest commit 2024-01-11 15:57:39 -06:00
Dmitry VerkhoturovandUmputun d143932924 add MIN_COMMENT_SIZE parameter 2023-12-02 12:16:26 -06:00
Dmitry Verkhoturov dcc7613409 allow disabling fancy HTML formatting
It might be necessary if the comments should preserve
original quotes instead of replacing them with angled ones.
2023-11-26 09:13:53 +01:00
Dmitry VerkhoturovandUmputun d04d2097f8 fix Commento import URL
Previously, it was not using the domain
and relying on another export format.
2023-11-20 10:59:05 -06:00
Dmitry Verkhoturov ce678bf967 fix Commento top-level comments import
Previously, top-level comments were incorrectly assigned
parent comment id "root", which made them non-root,
so they are not returned when requested
in the `/find?format=tree` API call.

To fix the previously imported comments, please export all your comments
and replace `"pid":"root"` with `"pid":""` and then re-import them.
2023-11-18 20:30:18 +01:00
Dmitry VerkhoturovandUmputun 69b18d3536 fix wrapped errors checks
As errors can be wrapped in recent versions of Go, the proper way
to check the error types are `errors.As` and `errors.Is`.
2023-10-10 23:36:04 -05:00
Dmitry VerkhoturovandUmputun f4358173c7 limit TitleExtractor to allow only Remark42 whitelisted domains
Allowed domains consist of `REMARK_URL` second-level domain (or whole IP in case it's IP like `127.0.0.1`) and `ALLOWED_HOSTS`. That is needed to prevent Remark42 from asking arbitrary servers and storing the page title as the comment.PostTitle.

Previous behaviour allowed the caller of the API to create a comment
with an arbitrary URL and learn the title of the page, which might be
accessible to the server Remark42 is installed on but not to the user
outside that network (CWE-918).
2023-10-10 23:34:35 -05:00
Dmitry VerkhoturovandUmputun 7a71d47556 remove all HTML tags from comment title and username
Previously, we stripped unsafe HTML tags but left some,
but it's not expected to have a link in a title or username,
so the new behaviour is stripping everything.
2023-10-10 12:41:26 -05:00
Dmitry VerkhoturovandUmputun 10e4686f1a reproduce report of CWE-918 from #1677 2023-10-10 11:43:56 -05:00
Umputun e30d4da455 update auth lib to master #1660
adopt tests for the mandatory provider check

fix leftover test for the server
2023-08-20 19:37:39 -05:00
Alexander GusmanandUmputun 366cc19c1b fix(rest): correct status code for telegram check token 2023-07-24 12:29:55 -05:00
Dmitry VerkhoturovandUmputun c72f30eabb remove proxied images from sanity check
Previously, proxied and local images were checked for presence in the
storage before previewing or posting the comment. That logic resulted in
 an inability to post with an image when a proxy for images is enabled,
 as proxied images are not downloaded to disk before the first time
 someone loads them, which could only happen after the user either
 previews or posts the message.

After this change, preview and post only checks the local images'
presence and ignore the proxied ones.
2023-07-23 12:10:52 -05:00
Dmitry VerkhoturovandUmputun 136d7e8215 switch from telegram_bot_username to telegram_notifications
Bot username is returned as an answer to subscribe request,
so knowing it in advance is unnecessary.
2023-06-29 10:52:00 -05:00
Dmitry VerkhoturovandUmputun 26f82ad95c don't allow relative links in comments
(url) is a text inserted by default and never an intended URL.

That additional validation will ensure that users won't post relative
links because they are rarely intended.
2023-04-09 23:30:21 -05:00
Dmitry VerkhoturovandUmputun a03c002df4 bump golangci-lint to latest 2023-04-02 01:21:33 -05:00
Dmitry VerkhoturovandUmputun 8357846818 add test JWT token generation instructions 2023-01-15 12:54:44 -06:00
Dmitry VerkhoturovandUmputun 385ea800a4 don't verify subscription email once more for email users
Previous behaviour is preserved for query parameters way of requesting
the subscription. The new behaviour with the possibility to confirm
the email right away without a separate /email/confirm call is enabled
only with request params sent in the request body, which was not a thing
before 27fc339e, which was merged just now and is not part
of any tagged version yet.
2023-01-09 03:17:25 -06:00
Dmitry Verkhoturov 27fc339e36 use the request body for email subscription endpoints
Previously, the endpoints were using query parameters.
After this change, the body is tried to be parsed.
2023-01-08 23:26:06 +01:00
Dmitry VerkhoturovandUmputun f1b65db2c7 prefer unused PreferServerCipherSuites param
This is not used since 1.17,
https://github.com/golang/go/commit/9d0819b27ca248f9949e7cf6bf7cb9fe7cf574e8
2022-11-13 12:02:40 -06:00
Dmitry VerkhoturovandUmputun c86bff8811 remove duplicate type definitions from function signatures
I haven't found a linter for these, so I had to catch these manually.
I found #757 to fix one of these, and I thought it would be good
to fix everything at once.
2022-11-13 11:51:51 -06:00
Dmitry VerkhoturovandUmputun 596b1045bd allow dots in site id during email user validation 2022-11-03 16:31:00 -05:00
Dmitry VerkhoturovandUmputun dd1ba9b518 clean up comment HasReplies cache on child comment deletion
Previously, the cache kept the entry and deletion of the parent comment
after child deletion was not possible for the rest
of cache life (5m) duration. Now it's possible to delete
a parent comment after the deletion of the child comment
by a user or admin.

Resolves #1481
2022-10-03 03:28:29 -05:00
Dmitry VerkhoturovandUmputun 0728b28856 bump golangci-lint, fix discovered problems
Also, improve the goveralls installation method.
2022-09-28 18:11:09 -05:00