Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
1188b58
chore: propagate changes from main into development (#1463)
Wikid82 Oct 3, 2026
3f333e6
refactor: add shared request helpers
Wikid82 Oct 3, 2026
7535a16
fix(security): harden input validation in the API layer
Wikid82 Oct 3, 2026
8510cb6
refactor: add shared request middleware
Wikid82 Oct 3, 2026
a1ff310
fix(security): harden request handling in the API layer
Wikid82 Oct 3, 2026
58d5b30
fix(security): harden account management in the API layer
Wikid82 Oct 3, 2026
e9a6c55
fix(security): harden request validation in the API layer
Wikid82 Oct 3, 2026
04e07f9
docs: update security configuration notes
Wikid82 Oct 3, 2026
0fa49c5
docs: update account management notes
Wikid82 Oct 3, 2026
4033d48
docs: update security configuration notes
Wikid82 Oct 3, 2026
e501538
test: add coverage for authentication edge cases
Wikid82 Oct 3, 2026
dbc0fc1
test: add coverage for authentication edge cases
Wikid82 Oct 3, 2026
e2e806a
test: update emergency reset rate-limit spec
Wikid82 Oct 3, 2026
79a1e0a
chore: widen codeql suppression line range
Wikid82 Oct 3, 2026
39ae2cf
chore: widen codeql suppression line range
Wikid82 Oct 3, 2026
09dccc6
chore: widen codeql suppression line range
Wikid82 Oct 3, 2026
0888108
chore: fix test lint warnings
Wikid82 Oct 3, 2026
2b9c7aa
chore: fix test lint warnings
Wikid82 Oct 3, 2026
66686ba
fix(security): harden request handling in the API layer (#1469)
Wikid82 Oct 3, 2026
d0b5b46
fix(security): harden account management in the API layer (#1470)
Wikid82 Oct 3, 2026
1b1e703
chore: merge development into fix/security-hardening-3
Wikid82 Oct 3, 2026
9e72b82
fix(security): harden request validation in the API layer (#1471)
Wikid82 Oct 3, 2026
52d63f0
chore: add Aikido API key env to Claude settings
Wikid82 Oct 3, 2026
a8e7d5e
chore: harden workflow triggers and checkout credentials
Wikid82 Oct 3, 2026
e69da96
deps: pin dnsimple-go to v8.3.1 in Caddy build
Wikid82 Oct 3, 2026
98a872e
fix: apply dnsimple-go pin via go get instead of xcaddy --with
Wikid82 Oct 3, 2026
dba3150
chore(docker): refresh bundled proxy toolchain image
Wikid82 Oct 3, 2026
f6c85c6
chore(docker): refresh bundled proxy toolchain image (#1475)
Wikid82 Oct 3, 2026
328b6f4
chore: build and test the powerdns plugin in the workspace
Wikid82 Oct 3, 2026
f15fd84
refactor: add shared helper for outbound provider requests
Wikid82 Oct 3, 2026
febd3cd
fix(security): harden URL handling in provider integrations
Wikid82 Oct 3, 2026
4cfb082
fix: validate DNS provider endpoint addresses
Wikid82 Oct 3, 2026
afcc35b
docs: document stricter address checks for provider integrations
Wikid82 Oct 3, 2026
b847047
chore: teach code scanning about the shared outbound request helpers
Wikid82 Oct 4, 2026
88440b7
chore(docker): set ownership at copy time instead of recursive chown …
Wikid82 Oct 4, 2026
1315289
test: handle ignored errors flagged by the full linter set
Wikid82 Oct 4, 2026
11b9792
chore: ignore plugin build leftovers in the powerdns module
Wikid82 Oct 4, 2026
16351cb
chore(deps): bump otelhttp to v0.72.0 and add powerdns to updater
Wikid82 Oct 4, 2026
0804794
fix(security): harden URL handling in provider integrations (#1476)
Wikid82 Oct 4, 2026
4312d88
chore: update dependency anchore/grype to v0.120.0
renovate[bot] Oct 4, 2026
34653e6
chore(deps): bump eslint-plugin-unicorn to v77
Wikid82 Oct 4, 2026
faea809
chore(deps): bump lucide-react from 1.50.0 to 1.51.0
Wikid82 Oct 4, 2026
9353d7e
chore(deps): override sitemap and uuid in docs site
Wikid82 Oct 4, 2026
b70837d
docs: fix broken links to contributor-only pages in the docs site
Wikid82 Oct 4, 2026
dc66f2c
chore(deps): allowlist unpatched braces and http-cache-semantics advi…
Wikid82 Oct 4, 2026
c34e060
chore: update dependency anchore/grype to v0.120.0 (#1484)
Wikid82 Oct 4, 2026
7eb6181
fix(security): pin pgproto3/v2 to v2.3.3 in crowdsec build
Wikid82 Oct 4, 2026
937a719
chore: update dependency uuid to v14
renovate[bot] Oct 4, 2026
3d88540
chore(docker): refresh bundled proxy toolchain image
Wikid82 Oct 4, 2026
2f4d88d
chore(docker): refresh bundled proxy toolchain image (#1486)
Wikid82 Oct 4, 2026
66cb560
Merge branch 'development' into renovate/uuid-14.x
Wikid82 Oct 4, 2026
78b0026
chore(docker): update GeoLite2-Country.mmdb checksum
Wikid82 Oct 4, 2026
c7b284c
chore: update dependency uuid to v14 (#1485)
Wikid82 Oct 4, 2026
07a8e68
chore(ci): stop persisting git credentials in test and scan workflow …
Wikid82 Oct 4, 2026
e4e6947
chore(ci): stop persisting git credentials in build and release workf…
Wikid82 Oct 4, 2026
bfc1987
chore(ci): push with an explicit token instead of persisted checkout …
Wikid82 Oct 4, 2026
cd64466
Merge branch 'development' into bot/update-geolite2-checksum
Wikid82 Oct 4, 2026
3b4f00b
chore(ci): scope workflow token permissions per job and guard workflo…
Wikid82 Oct 4, 2026
d77293e
chore(ci): scope package write permissions to the jobs that publish
Wikid82 Oct 4, 2026
80aab86
chore(ci): drop workflow_run trigger from PR security scan
Wikid82 Oct 4, 2026
4a71450
chore: move serialize-javascript script to docs-site directory
Wikid82 Oct 4, 2026
b4dac5a
chore(deps): bump http-cache-semantics override to 4.3.0
Wikid82 Oct 4, 2026
37210e2
chore(docker): update GeoLite2-Country.mmdb checksum (#1487)
Wikid82 Oct 4, 2026
4e5c7b5
chore(deps): bump lucide-react from 1.51.0 to 1.52.0
Wikid82 Oct 4, 2026
518526b
chore(docs-site): override feed to ^6.0.0 and add update script
Wikid82 Oct 5, 2026
735549c
docs: add Aikido security audit report badge to README
Wikid82 Oct 5, 2026
c1f9bf0
docs: replace example emergency tokens with placeholders
Wikid82 Oct 5, 2026
82cc160
test: use obviously fake token in emergency server redaction test
Wikid82 Oct 5, 2026
4da6d86
docs: scrub example emergency token from archived docs
Wikid82 Oct 5, 2026
68a8d2f
chore: remove Aikido API key from tracked Claude settings
Wikid82 Oct 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/codeql-custom-model.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@
# - IPv6 Unique Local: fc00::/7
#
# Reference: /docs/plans/current_spec.md
#
# NOTE: this file is NOT loaded by code scanning. Data extensions are only
# picked up from model packs under .github/codeql/extensions/ (see
# charon-safehttp-models there). Entries below are kept for documentation; note
# that a sinkModel marks a request-forgery sink rather than a sanitizer, so
# they should not be moved into a pack as-is (use barrierModel instead).
extensions:
# =============================================================================
# SSRF SANITIZER MODELS
Expand Down
8 changes: 7 additions & 1 deletion .github/codeql/codeql-suppressions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@
suppressions:
- rule_id: go/cookie-secure-not-set
path: backend/internal/api/handlers/auth_handler.go
line: 187
line_range:
start: 187
end: 205
reason: >
Secure is false only when isLocalRequest(c) AND scheme != "https"
(loopback/RFC1918/IPv6-ULA/Tailscale-CGNAT origin over plain HTTP) β€”
Expand All @@ -43,6 +45,10 @@ suppressions:
the documented fallback for that case. See
docs/issues/codeql-cookie-suppression-not-honored.md for the full
investigation history.
Extended 2026-10-03: the request-origin/auth handler changes in the
security hardening PRs shift the SetCookie sink between lines 187 and
~202 depending on merge state, so the entry is widened to a
line_range; this is the only SetCookie call in the file.
added: "2026-08-04"
review_by: "2026-11-04"

Expand Down
12 changes: 12 additions & 0 deletions .github/codeql/extensions/charon-safehttp-models/codeql-pack.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# CodeQL model pack: data extensions for Charon's own helpers.
#
# Code scanning (github/codeql-action) automatically discovers model packs
# under .github/codeql/extensions/, so this pack applies to CI without being
# listed in .github/codeql/codeql-config.yml.
name: charon/safehttp-models
version: 0.0.1
library: true
extensionTargets:
codeql/go-all: "*"
dataExtensions:
- models/**/*.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Barrier models for the shared outbound-request helpers in
# backend/pkg/safehttp.
#
# The values returned by these functions are safe to use as a request URL:
# - ValidateURLSyntax / ValidateURL reject non-HTTP(S) schemes, embedded
# credentials, and literal blocked addresses (ValidateURL also resolves
# hostnames), and return a parsed *url.URL.
# - JoinPath only appends individually escaped path segments to a validated
# base URL (dot segments, separators, and control characters are rejected),
# so the scheme and host of the result always come from that base.
# The dialer inside safehttp.NewClient re-validates every connection address
# and is the authoritative control; these barriers only tell the query where
# validation has already happened.
extensions:
- addsTo:
pack: codeql/go-all
extensible: barrierModel
data:
- ["github.com/Wikid82/charon/backend/pkg/safehttp", "", False, "ValidateURLSyntax", "", "", "ReturnValue[0]", "request-forgery", "manual"]
- ["github.com/Wikid82/charon/backend/pkg/safehttp", "", False, "ValidateURL", "", "", "ReturnValue[0]", "request-forgery", "manual"]
- ["github.com/Wikid82/charon/backend/pkg/safehttp", "", False, "JoinPath", "", "", "ReturnValue[0]", "request-forgery", "manual"]
26 changes: 26 additions & 0 deletions .github/renovate.json
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,19 @@
"depNameTemplate": "github.com/libdns/vercel",
"datasourceTemplate": "go",
"versioningTemplate": "semver"
},
{
"customType": "regex",
"description": "Track dnsimple-go/v8 forced transitive version ARG in Dockerfile",
"managerFilePatterns": [
"/^Dockerfile$/"
],
"matchStrings": [
"ARG CADDY_DNS_DNSIMPLE_GO_VERSION=(?<currentValue>[^\\s]+)"
],
"depNameTemplate": "github.com/dnsimple/dnsimple-go/v8",
"datasourceTemplate": "go",
"versioningTemplate": "semver"
}
],
"github-actions": {
Expand Down Expand Up @@ -892,6 +905,19 @@
],
"enabled": false
},
{
"description": "The bundled powerdns plugin consumes the in-repo backend module through a local replace directive; never let Renovate resolve or bump it.",
"matchManagers": [
"gomod"
],
"matchFileNames": [
"plugins/powerdns/go.mod"
],
"matchPackageNames": [
"github.com/Wikid82/charon/backend"
],
"enabled": false
},
{
"description": "Group GitHub Actions non-major updates into one PR",
"matchManagers": [
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/benchmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ jobs:
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
# For pull_request events, use the branch HEAD SHA (not the ephemeral merge
# commit that github.sha resolves to), which is directly fetchable by SHA.
# For workflow_run events fall back to the triggering HEAD SHA.
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/build-offline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/codecov-upload.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ jobs:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
fetch-depth: 0
ref: ${{ github.sha }}

Expand Down Expand Up @@ -177,6 +178,7 @@ jobs:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
fetch-depth: 0
ref: ${{ github.sha }}

Expand Down Expand Up @@ -214,6 +216,7 @@ jobs:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
fetch-depth: 0
ref: ${{ github.sha }}

Expand Down
1 change: 1 addition & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ jobs:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
# Use github.ref (full ref path) instead of github.ref_name:
# - push/schedule: resolves to refs/heads/<branch>, checking out latest HEAD
# - pull_request: resolves to refs/pull/<n>/merge, the correct PR merge ref
Expand Down
8 changes: 7 additions & 1 deletion .github/workflows/container-prune.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ on:
default: '30'

permissions:
packages: write
contents: read

jobs:
prune-ghcr:
permissions:
contents: read
packages: write # delete old GHCR image versions
runs-on: ubuntu-latest
if: github.event_name != 'workflow_dispatch' || github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
strategy:
Expand All @@ -42,6 +44,8 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false

- name: Install tools
run: |
Expand Down Expand Up @@ -124,6 +128,8 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false

- name: Install tools
run: |
Expand Down
8 changes: 7 additions & 1 deletion .github/workflows/docker-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ jobs:
# Actions' `on:` block cannot reference expressions/env, so there is no shared source).
# `nightly` is deliberately excluded β€” it is not in `push.branches`, so a PR headed at
# `nightly` never races a `push`-triggered run of this workflow.
if: ${{ (github.event_name != 'workflow_run' || (github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.name == 'Docker Lint' && github.event.workflow_run.path == '.github/workflows/docker-lint.yml')) && (github.event_name != 'pull_request' || !contains(fromJSON('["main","development"]'), github.head_ref)) }}
if: ${{ (github.event_name != 'workflow_run' || (github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.name == 'Docker Lint' && github.event.workflow_run.path == '.github/workflows/docker-lint.yml' && github.event.workflow_run.head_repository.full_name == github.repository)) && (github.event_name != 'pull_request' || !contains(fromJSON('["main","development"]'), github.head_ref)) }}
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
Expand All @@ -113,6 +113,7 @@ jobs:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
ref: ${{ env.TRIGGER_HEAD_SHA }}
fetch-depth: 0
- name: Normalize image name
Expand Down Expand Up @@ -448,6 +449,7 @@ jobs:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
ref: ${{ env.TRIGGER_HEAD_SHA }}
- name: Normalize image name
run: |
Expand Down Expand Up @@ -534,6 +536,7 @@ jobs:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
ref: ${{ env.TRIGGER_HEAD_SHA }}
- name: Normalize image name
run: |
Expand Down Expand Up @@ -647,6 +650,7 @@ jobs:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
ref: ${{ env.TRIGGER_HEAD_SHA }}
- name: Normalize image name
run: |
Expand Down Expand Up @@ -1199,6 +1203,8 @@ jobs:
steps:
- name: Checkout repository for Trivy ignore rules
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false

- name: Normalize image name
run: |
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/docker-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false

- name: Run Hadolint
uses: hadolint/hadolint-action@06be81baf89a55ffd0e24b8f04a4185738dd3387 # v3.5.0
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/docs-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ jobs:
# Step 1: Get the code
- name: πŸ“₯ Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false

# Step 2: Set up Node.js
- name: πŸ”§ Set up Node.js
Expand Down
15 changes: 11 additions & 4 deletions .github/workflows/docs-to-issues.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@ env:
NODE_VERSION: '24.21.0'

permissions:
contents: write
issues: write
pull-requests: write
contents: read

jobs:
convert-docs:
name: Convert Markdown to Issues
permissions:
contents: write # push moved issue files back to the branch
issues: write
pull-requests: write
runs-on: ubuntu-latest
if: >-
github.actor != 'github-actions[bot]' &&
Expand All @@ -47,6 +49,7 @@ jobs:
with:
fetch-depth: 2
ref: ${{ github.event.workflow_run.head_sha || github.sha }}
persist-credentials: false

- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
Expand Down Expand Up @@ -346,14 +349,18 @@ jobs:
if: steps.process.outputs.created_count != '0' && github.event.inputs.dry_run != 'true'
env:
BRANCH_NAME: ${{ github.event.workflow_run.head_branch || github.ref_name }}
PUSH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add docs/issues/
# Removed [skip ci] to allow CI checks to run on PRs
# Infinite loop protection: path filter excludes docs/issues/created/** AND github.actor guard prevents bot loops
git diff --staged --quiet || git commit -m "chore: move processed issue files to created/"
git push origin "HEAD:refs/heads/${BRANCH_NAME}"
# Authenticate this push with an explicit token (checkout does not persist one).
AUTH_HEADER="AUTHORIZATION: basic $(printf 'x-access-token:%s' "$PUSH_TOKEN" | base64 -w0)"
echo "::add-mask::${AUTH_HEADER#AUTHORIZATION: basic }"
git -c http.https://github.com/.extraheader="$AUTH_HEADER" push origin "HEAD:refs/heads/${BRANCH_NAME}"

- name: Summary
if: always()
Expand Down
11 changes: 2 additions & 9 deletions .github/workflows/dry-run-history-rewrite.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
name: History Rewrite Dry-Run

on:
workflow_run:
workflows: ["Docker Build, Publish & Test"]
types: [completed]
schedule:
- cron: '0 2 * * *' # daily at 02:00 UTC
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event.workflow_run.head_branch || github.head_ref || github.ref_name }}
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.head_ref || github.ref_name }}
cancel-in-progress: true

permissions:
Expand All @@ -19,16 +16,12 @@ jobs:
preview-history:
name: Dry-run preview for history rewrite
runs-on: ubuntu-latest
if: >-
${{ github.event_name != 'workflow_run' ||
(github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.head_repository.full_name == github.repository) }}
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
fetch-depth: 0
ref: ${{ github.event.workflow_run.head_sha || github.sha }}
persist-credentials: false

- name: Debug git info
run: |
Expand Down
Loading
Loading