Fix security issues #38

Merged
stb merged 11 commits from security-fixes into main 2026-11-15 13:42:03 +01:00

2026-11-15

stb
Merge branch 'main' into security-fixes
All checks were successful
Build (and tag) Images / Build data_handler Image (push) Successful in 42s
Build (and tag) Images / Build web Image (push) Successful in 57s
2026-11-15 13:38:04 +01:00
stb
Merge branch 'main' into security-fixes
All checks were successful
Build (and tag) Images / Build data_handler Image (push) Successful in 40s
Build (and tag) Images / Build web Image (push) Successful in 1m2s
2026-11-15 13:28:46 +01:00
chore: Reverts workflow changes
Some checks failed
Build (and tag) Images / build (push) Has been cancelled
The image build workflow is handled separately in the kaniko-build branch;
this pull request no longer changes it.
2026-11-15 11:57:18 +01:00
fix: Builds images with kaniko
All checks were successful
Build (and tag) Images / build (push) Successful in 1m23s
There are no Windows runners; build the images with kaniko in a container
on the `docker` runner, as on the link-updates branch, while keeping the
publishing restrictions:

- only pushes to refs/heads/main publish, as `latest` and `sha-<commit>`
- other refs build with --no-push under a ci-<commit> tag
- registry credentials are only passed to the build when publishing

The docker compose smoke test is dropped, as there is no Docker daemon
inside the kaniko container.
2026-11-15 11:48:03 +01:00
Merge remote-tracking branch 'origin/main' into security-fixes
Some checks failed
Build (and tag) Images / build (push) Has been cancelled
2026-11-15 11:45:52 +01:00
fix: Corrects country code check in statistics filter
Some checks failed
Build (and tag) Images / build (push) Failing after 12s
Operator precedence made the check always true; it now accepts two capital letters or '--' as intended.
2026-11-15 11:36:49 +01:00
fix: Escapes generated SQL and validates sequence number
create_camera_update_statements.php wrote OSM tag keys and values unescaped
into /migrations/*.sql. Values are now escaped and node ids cast to int.
The sequence number argument must be numeric and is bound as a parameter
instead of being concatenated into SQL and the output path.
2026-11-15 11:36:49 +01:00
fix: Publishes images only from main
Every pushed ref built and pushed images, with the tag derived from the ref
name. A branch named "latest" or a git tag named "main" therefore
overwrote the production image, and ref names were interpolated into shell
scripts unquoted (script injection).

- images are only pushed for pushes to refs/heads/main
- other refs are built and tested with a ci-<sha> tag, never pushed
- registry login happens only when publishing, after the compose test
- main additionally pushes an immutable sha-<sha> tag for pinning
- expression values are passed to scripts via env

The registry credentials still need to be restricted to main on the
Forgejo side, since a pushed branch can modify this workflow.
2026-11-15 11:36:49 +01:00
fix: Hardens web container
- document root is owned by root and not writable by www-data
  (the base image ships /var/www/html as www-data with mode 1777)
- uses php.ini-production, so errors are not shown to clients
- disables directory listings, expose_php and the detailed server signature
2026-11-15 11:36:49 +01:00
fix: Escapes location search results
Nominatim results were inserted via innerHTML and loaded as a JSONP script
with an unencoded query. Results are now fetched as JSON, the query is URL
encoded, text is escaped and coordinates must be numeric.
2026-11-15 11:36:49 +01:00
fix: Escapes OSM tag data in camera popups
camera.php built its JSON by hand with htmlentities(), which leaves
backslashes intact, and the client parsed it with eval() and inserted tag
values into the popup as HTML. A tag value such as <img ...> therefore
became live markup (stored XSS for anyone able to edit OSM data), and a lone
backslash broke parsing of the whole response.

- camera.php now builds the response with json_encode() and returns raw values
- tags named lat, lon, id, count, multi or poly no longer override the
  fields set by the server
- error responses no longer include database error messages
- the client uses JSON.parse() and escapes all keys and values; only
  http(s) URLs are rendered as links/images
2026-11-15 11:36:49 +01:00