Skip to content

feat(gdpr): IP/privacy audit (PR2 of #6701)#7547

Open
JohnMcLear wants to merge 9 commits intodevelopfrom
feat-gdpr-ip-audit
Open

feat(gdpr): IP/privacy audit (PR2 of #6701)#7547
JohnMcLear wants to merge 9 commits intodevelopfrom
feat-gdpr-ip-audit

Conversation

@JohnMcLear
Copy link
Copy Markdown
Member

Summary

  • Fix four log-sites that emitted raw IPs despite disableIPlogging=true: the PadMessageHandler rate-limit warn, both auth-log calls in webaccess, and the import/export rate-limit warn.
  • Replace the boolean with a tri-state ipLogging: "full" | "truncated" | "anonymous" (default "anonymous"). Every IP log site now routes through a single anonymizeIp() helper.
  • Keep disableIPlogging working for one release via a load-time shim that maps true"anonymous", false"full" and emits a WARN when only the legacy setting is set.
  • Drop the dead clientVars.clientIp placeholder (always '127.0.0.1'; no client code read it). pad.getClientIp() is retained as a plugin-compat shim returning the same literal.
  • doc/privacy.md documents exactly what Etherpad logs, where, and how to configure it.

Part of the GDPR work tracked in #6701. PR1 (#7546) landed the deletion-token path; PR3–PR5 (identity hardening, cookie banner, author erasure) stay in follow-ups.

Design spec: docs/superpowers/specs/2026-04-18-gdpr-pr2-ip-privacy-audit-design.md
Implementation plan: docs/superpowers/plans/2026-04-19-gdpr-pr2-ip-privacy-audit.md

Test plan

  • pnpm --filter ep_etherpad-lite run ts-check
  • 15 anonymizeIp unit tests (v4 / v6 / v4-mapped / invalid / empty / all three modes)
  • 8 ipLoggingSetting integration tests (each mode + shim mapping)
  • api.ts regression (ClientVarPayload / REST surface)

@qodo-free-for-open-source-projects
Copy link
Copy Markdown

Review Summary by Qodo

GDPR IP/privacy audit: tri-state ipLogging setting and leak fixes

✨ Enhancement 🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Replace boolean disableIPlogging with tri-state ipLogging setting
  - Supports "anonymous" (default), "truncated", "full" modes
  - Deprecation shim maps legacy boolean for one release cycle
• Fix four IP logging leaks where disableIPlogging was silently ignored
  - Rate-limit warnings in PadMessageHandler and import/export
  - Authentication failure/success logs in webaccess
• Remove dead clientVars.clientIp placeholder (always '127.0.0.1', never read)
• Add comprehensive privacy documentation and operator-facing IP handling guide
Diagram
flowchart LR
  A["Legacy disableIPlogging<br/>boolean"] -->|"Deprecation shim<br/>at load time"| B["New ipLogging<br/>tri-state"]
  B -->|"'anonymous'"| C["ANONYMOUS<br/>in logs"]
  B -->|"'truncated'"| D["Last octet zeroed<br/>IPv4/IPv6 /48"]
  B -->|"'full'"| E["Full IP<br/>in logs"]
  F["5 logging sites<br/>PadMessageHandler<br/>SocketIORouter<br/>webaccess<br/>importexport"] -->|"Route through<br/>anonymizeIp helper"| B
  G["clientVars.clientIp<br/>placeholder"] -->|"Remove<br/>dead code"| H["Cleaner type<br/>surface"]
  I["doc/privacy.md"] -->|"Operator<br/>documentation"| J["Clear IP handling<br/>statement"]
Loading

Grey Divider

File Changes

1. src/node/utils/anonymizeIp.ts ✨ Enhancement +35/-0

New pure helper for IP anonymization

src/node/utils/anonymizeIp.ts


2. src/node/utils/Settings.ts ✨ Enhancement +14/-1

Add tri-state ipLogging with deprecation shim

src/node/utils/Settings.ts


3. src/node/handler/PadMessageHandler.ts 🐞 Bug fix +7/-7

Route all IP logs through anonymizeIp helper

src/node/handler/PadMessageHandler.ts


View more (12)
4. src/node/handler/SocketIORouter.ts 🐞 Bug fix +2/-1

Replace ternary with anonymizeIp call

src/node/handler/SocketIORouter.ts


5. src/node/hooks/express/webaccess.ts 🐞 Bug fix +6/-2

Fix auth log IP leaks via anonymizeIp

src/node/hooks/express/webaccess.ts


6. src/node/hooks/express/importexport.ts 🐞 Bug fix +3/-1

Fix rate-limit warn IP leak via anonymizeIp

src/node/hooks/express/importexport.ts


7. src/static/js/types/SocketIOMessage.ts 🐞 Bug fix +0/-2

Remove dead clientIp field from types

src/static/js/types/SocketIOMessage.ts


8. src/static/js/pad.ts 🐞 Bug fix +4/-1

Convert getClientIp to plugin-compat shim

src/static/js/pad.ts


9. src/tests/backend/specs/anonymizeIp.ts 🧪 Tests +53/-0

Unit tests for anonymizeIp helper

src/tests/backend/specs/anonymizeIp.ts


10. src/tests/backend/specs/ipLoggingSetting.ts 🧪 Tests +70/-0

Integration tests for ipLogging modes

src/tests/backend/specs/ipLoggingSetting.ts


11. doc/privacy.md 📝 Documentation +61/-0

Operator-facing privacy and IP handling guide

doc/privacy.md


12. settings.json.template ⚙️ Configuration changes +16/-1

Add ipLogging setting with documentation

settings.json.template


13. settings.json.docker ⚙️ Configuration changes +9/-1

Add ipLogging environment variable support

settings.json.docker


14. docs/superpowers/specs/2026-04-18-gdpr-pr2-ip-privacy-audit-design.md 📝 Documentation +206/-0

Design specification for IP audit changes

docs/superpowers/specs/2026-04-18-gdpr-pr2-ip-privacy-audit-design.md


15. docs/superpowers/plans/2026-04-19-gdpr-pr2-ip-privacy-audit.md 📝 Documentation +745/-0

Detailed implementation plan with TDD tasks

docs/superpowers/plans/2026-04-19-gdpr-pr2-ip-privacy-audit.md


Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects
Copy link
Copy Markdown

qodo-free-for-open-source-projects bot commented Apr 19, 2026

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (3) 📎 Requirement gaps (0)

Grey Divider


Action required

1. IP log-site fixes untested 📘 Rule violation ☼ Reliability
Description
The PR fixes multiple IP logging leaks, but the added tests only validate anonymizeIp() and shim
mapping, not that the updated log call sites actually use it. This risks regressions where raw IPs
could reappear in logs without failing CI.
Code

src/node/hooks/express/webaccess.ts[R182-186]

+      httpLogger.info(
+          `Failed authentication from IP ${anonymizeIp(req.ip, settings.ipLogging)}`);
      if (await aCallFirst0('authnFailure', {req, res})) return;
      if (await aCallFirst0('authFailure', {req, res, next})) return;
      // No plugin handled the authentication failure. Fall back to basic authentication.
Evidence
PR Compliance ID 2 requires a regression test for bug fixes. The updated auth log lines now wrap
req.ip with anonymizeIp(...), but the added tests do not exercise these logging sites (they only
call anonymizeIp directly and reimplement the shim logic).

src/node/hooks/express/webaccess.ts[182-212]
src/tests/backend/specs/ipLoggingSetting.ts[15-68]
Best Practice: Repository guidelines

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Bug fixes for IP logging leaks are not covered by a regression test that would fail if a log site reverted to logging raw IPs.

## Issue Context
The PR updates multiple log call sites (auth logs, rate-limit warnings, socket connect logs) to route through `anonymizeIp(...)`. The newly added tests validate the helper and shim behavior but do not exercise the actual log-producing code paths.

## Fix Focus Areas
- src/node/hooks/express/webaccess.ts[182-212]
- src/node/hooks/express/importexport.ts[20-24]
- src/node/handler/PadMessageHandler.ts[279-285]
- src/node/handler/SocketIORouter.ts[62-66]
- src/tests/backend/specs/ipLoggingSetting.ts[1-70]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. ipLogging changes default behavior 📘 Rule violation ⚙ Maintainability
Description
ipLogging defaults to anonymous, changing the default logging behavior rather than keeping prior
behavior unless explicitly enabled. This introduces a behavior change without a feature flag gating
it off by default.
Code

src/node/utils/Settings.ts[R501-503]

   */
  disableIPlogging: false,
+  ipLogging: 'anonymous',
Evidence
PR Compliance ID 5 requires new functionality to be gated and disabled by default such that behavior
is unchanged unless explicitly enabled. The new ipLogging setting is introduced with a default of
anonymous in runtime defaults and templates, which changes default behavior immediately.

src/node/utils/Settings.ts[501-503]
settings.json.template[476-493]
Best Practice: Repository guidelines

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new `ipLogging` functionality changes default behavior (`anonymous`) rather than preserving the prior default behavior unless explicitly enabled.

## Issue Context
Compliance requires new behavior to be off by default (behavior unchanged) unless explicitly enabled via a flag/config.

## Fix Focus Areas
- src/node/utils/Settings.ts[499-503]
- settings.json.template[475-493]
- settings.json.docker[478-489]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. ipLogging not validated 🐞 Bug ≡ Correctness
Description
If settings.ipLogging is set to an unsupported value (including null), anonymizeIp() will treat it
as "truncated" instead of failing or falling back to the documented default "anonymous". This can
silently change privacy behavior and produce unexpected partially-redacted IPs in logs.
Code

src/node/utils/anonymizeIp.ts[R23-34]

+export const anonymizeIp = (ip: string | null | undefined, mode: IpLogging): string => {
+  if (ip == null || ip === '') return 'ANONYMOUS';
+  if (mode === 'anonymous') return 'ANONYMOUS';
+  if (mode === 'full') return ip;
+  // truncated
+  const mapped = IPV4_MAPPED.exec(ip);
+  if (mapped != null) return `::ffff:${mapped[1].replace(/\.\d+$/, '.0')}`;
+  switch (isIP(ip)) {
+    case 4: return ip.replace(/\.\d+$/, '.0');
+    case 6: return truncateIpv6(ip);
+    default: return 'ANONYMOUS';
+  }
Evidence
anonymizeIp() has explicit branches only for 'anonymous' and 'full'; every other value falls into
the 'truncated' path. Settings.reloadSettings() introduces the new ipLogging setting but does not
validate/normalize it (unlike other settings such as skinName/socketTransportProtocols), and
storeSettings() copies config values verbatim into settings.ipLogging.

src/node/utils/anonymizeIp.ts[23-34]
src/node/utils/Settings.ts[733-760]
src/node/utils/Settings.ts[961-996]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`settings.ipLogging` is consumed at runtime as a trusted union, but config loading does not validate it. Any invalid value silently causes `anonymizeIp()` to behave as if mode is `truncated`.

## Issue Context
- `storeSettings()` copies parsed config values into `settings` with no schema validation.
- `anonymizeIp()` treats all non-`anonymous`/`full` values as `truncated`.

## Fix Focus Areas
- src/node/utils/Settings.ts[961-996]
- src/node/utils/anonymizeIp.ts[23-34]

## What to change
1. In `reloadSettings()` (after `storeSettings(...)`), validate `settings.ipLogging`.
  - Allowed values: `anonymous`, `truncated`, `full`.
  - If invalid (including null/undefined), `logger.error` or `logger.warn` and set `settings.ipLogging = 'anonymous'`.
2. Consider making `anonymizeIp()` defensive:
  - Use an explicit `switch (mode)` with a `default` that returns `'ANONYMOUS'` (privacy-safe) or throws in dev/test.
3. Add/adjust a backend test asserting invalid `ipLogging` values are rejected or normalized to `'anonymous'`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

4. clientIp removed without deprecation 📘 Rule violation ⚙ Maintainability
Description
clientVars.clientIp (and its type surface) is removed without a deprecation period or WARN-level
signal, which can break plugins or custom clients that relied on the field. This violates the
deprecation-first and backward-compat expectations.
Code

src/static/js/types/SocketIOMessage.ts[L34-37]

export type ServerVar = {
  rev: number
-  clientIp: string
  padId: string
Evidence
The PR removes clientIp from the socket client var types and stops populating it in
server-generated clientVars, which is an externally observable interface change. There is no
accompanying deprecation period (keep field for one release) or WARN indicating upcoming removal,
and this can introduce avoidable breaking behavior for existing integrations.

src/static/js/types/SocketIOMessage.ts[34-37]
src/static/js/types/SocketIOMessage.ts[64-68]
src/node/handler/PadMessageHandler.ts[1021-1031]
Best Practice: Repository guidelines
Best Practice: Repository guidelines

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`clientVars.clientIp` is removed from the server payload and TypeScript types without a deprecation period or WARN-level notice, creating a potential breaking change for plugins/custom clients.

## Issue Context
Even if core client code does not read the field, third-party code can. Compliance requires deprecation with a warning before removal and encourages backward compatibility.

## Fix Focus Areas
- src/node/handler/PadMessageHandler.ts[1021-1031]
- src/static/js/types/SocketIOMessage.ts[33-39]
- src/static/js/types/SocketIOMessage.ts[63-70]
- src/static/js/pad.ts[405-409]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Legacy setting silently ignored 🐞 Bug ⚙ Maintainability
Description
The disableIPlogging→ipLogging shim only runs when ipLogging is absent, but settings.json.docker now
always includes ipLogging, so disableIPlogging can be silently ignored with no deprecation warning.
This makes Docker/operator migrations confusing because DISABLE_IP_LOGGING may appear to work while
actually having no effect.
Code

src/node/utils/Settings.ts[R967-976]

+    // Deprecation shim: if the operator set the legacy boolean `disableIPlogging`
+    // without also setting the new tri-state `ipLogging`, map the boolean over
+    // once and emit a WARN. An explicitly-set `ipLogging` always wins.
+    if (settingsParsed != null && 'disableIPlogging' in (settingsParsed as any) &&
+        !('ipLogging' in (settingsParsed as any))) {
+      logger.warn(
+          '`disableIPlogging` is deprecated; use `ipLogging: "anonymous"` ' +
+          '(or "truncated" / "full") instead.');
+      settings.ipLogging = (settingsParsed as any).disableIPlogging ? 'anonymous' : 'full';
+    }
Evidence
reloadSettings() only applies the legacy mapping when the parsed settings contain disableIPlogging
but do not contain ipLogging. The Docker settings file added in this PR always defines ipLogging
(with a default), so the condition is false and the deprecation shim warning/mapping will not
execute in that configuration.

src/node/utils/Settings.ts[967-976]
settings.json.docker[478-489]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`disableIPlogging` is deprecated, but in common configs that include both keys (notably `settings.json.docker`), the legacy value is ignored without any warning because the shim only runs when `ipLogging` is absent.

## Issue Context
- The project includes both keys in Docker settings, but Etherpad code paths now read only `settings.ipLogging`.
- Operators may continue setting `DISABLE_IP_LOGGING` and never realize it is ineffective.

## Fix Focus Areas
- src/node/utils/Settings.ts[961-977]
- settings.json.docker[478-489]

## What to change
1. In `reloadSettings()`, add a warning path for when both `disableIPlogging` and `ipLogging` are present in the parsed config:
  - If `disableIPlogging` is set and `ipLogging` is set, log a WARN that `disableIPlogging` is deprecated and ignored because `ipLogging` is present.
  - Optionally, only warn when the two conflict (e.g., `disableIPlogging=false` but `ipLogging!=='full'`).
2. Consider removing `disableIPlogging` from `settings.json.docker` (or documenting it as deprecated/no-op) to avoid encouraging continued use.
3. Add a small test (or extend `ipLoggingSetting.ts`) to assert the WARN is emitted when both keys are present.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Docker docs miss IP_LOGGING 🐞 Bug ⚙ Maintainability
Description
Docker documentation still lists only DISABLE_IP_LOGGING even though settings.json.docker now
supports the new IP_LOGGING tri-state. This will lead operators to use the deprecated env var and
miss the new "truncated" mode.
Code

settings.json.docker[R478-489]

  /*
-   * Privacy: disable IP logging
+   * Controls what Etherpad writes to its logs about client IP addresses.
+   * Allowed values: "anonymous" (default), "truncated", "full".
+   * See settings.json.template for details.
+   */
+  "ipLogging": "${IP_LOGGING:anonymous}",
+
+  /*
+   * Deprecated — use `ipLogging` above. Still honoured for one release
+   * cycle: true → "anonymous", false → "full".
   */
  "disableIPlogging": "${DISABLE_IP_LOGGING:false}",
Evidence
The Docker settings template introduces an IP_LOGGING env var placeholder, but doc/docker.md and
doc/docker.adoc still document only DISABLE_IP_LOGGING under Logging variables.

settings.json.docker[478-489]
doc/docker.md[178-184]
doc/docker.adoc[379-394]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Docker operator docs do not mention the new `IP_LOGGING` env var and still present `DISABLE_IP_LOGGING` as the privacy control.

## Issue Context
`settings.json.docker` now has:
- `ipLogging`: `${IP_LOGGING:anonymous}`
- `disableIPlogging`: `${DISABLE_IP_LOGGING:false}` (deprecated)

## Fix Focus Areas
- doc/docker.md[178-184]
- doc/docker.adoc[379-394]
- README.md (docker-compose snippet if needed)

## What to change
1. Update Docker docs tables to add `IP_LOGGING` with allowed values (`anonymous`/`truncated`/`full`) and default `anonymous`.
2. Mark `DISABLE_IP_LOGGING` as deprecated and point users to `IP_LOGGING`.
3. (Optional) Update docker-compose examples to use `IP_LOGGING` instead of always setting `DISABLE_IP_LOGGING`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Comment on lines +182 to 186
httpLogger.info(
`Failed authentication from IP ${anonymizeIp(req.ip, settings.ipLogging)}`);
if (await aCallFirst0('authnFailure', {req, res})) return;
if (await aCallFirst0('authFailure', {req, res, next})) return;
// No plugin handled the authentication failure. Fall back to basic authentication.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Ip log-site fixes untested 📘 Rule violation ☼ Reliability

The PR fixes multiple IP logging leaks, but the added tests only validate anonymizeIp() and shim
mapping, not that the updated log call sites actually use it. This risks regressions where raw IPs
could reappear in logs without failing CI.
Agent Prompt
## Issue description
Bug fixes for IP logging leaks are not covered by a regression test that would fail if a log site reverted to logging raw IPs.

## Issue Context
The PR updates multiple log call sites (auth logs, rate-limit warnings, socket connect logs) to route through `anonymizeIp(...)`. The newly added tests validate the helper and shim behavior but do not exercise the actual log-producing code paths.

## Fix Focus Areas
- src/node/hooks/express/webaccess.ts[182-212]
- src/node/hooks/express/importexport.ts[20-24]
- src/node/handler/PadMessageHandler.ts[279-285]
- src/node/handler/SocketIORouter.ts[62-66]
- src/tests/backend/specs/ipLoggingSetting.ts[1-70]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines 501 to +503
*/
disableIPlogging: false,
ipLogging: 'anonymous',
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. iplogging changes default behavior 📘 Rule violation ⚙ Maintainability

ipLogging defaults to anonymous, changing the default logging behavior rather than keeping prior
behavior unless explicitly enabled. This introduces a behavior change without a feature flag gating
it off by default.
Agent Prompt
## Issue description
The new `ipLogging` functionality changes default behavior (`anonymous`) rather than preserving the prior default behavior unless explicitly enabled.

## Issue Context
Compliance requires new behavior to be off by default (behavior unchanged) unless explicitly enabled via a flag/config.

## Fix Focus Areas
- src/node/utils/Settings.ts[499-503]
- settings.json.template[475-493]
- settings.json.docker[478-489]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +23 to +34
export const anonymizeIp = (ip: string | null | undefined, mode: IpLogging): string => {
if (ip == null || ip === '') return 'ANONYMOUS';
if (mode === 'anonymous') return 'ANONYMOUS';
if (mode === 'full') return ip;
// truncated
const mapped = IPV4_MAPPED.exec(ip);
if (mapped != null) return `::ffff:${mapped[1].replace(/\.\d+$/, '.0')}`;
switch (isIP(ip)) {
case 4: return ip.replace(/\.\d+$/, '.0');
case 6: return truncateIpv6(ip);
default: return 'ANONYMOUS';
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

3. Iplogging not validated 🐞 Bug ≡ Correctness

If settings.ipLogging is set to an unsupported value (including null), anonymizeIp() will treat it
as "truncated" instead of failing or falling back to the documented default "anonymous". This can
silently change privacy behavior and produce unexpected partially-redacted IPs in logs.
Agent Prompt
## Issue description
`settings.ipLogging` is consumed at runtime as a trusted union, but config loading does not validate it. Any invalid value silently causes `anonymizeIp()` to behave as if mode is `truncated`.

## Issue Context
- `storeSettings()` copies parsed config values into `settings` with no schema validation.
- `anonymizeIp()` treats all non-`anonymous`/`full` values as `truncated`.

## Fix Focus Areas
- src/node/utils/Settings.ts[961-996]
- src/node/utils/anonymizeIp.ts[23-34]

## What to change
1. In `reloadSettings()` (after `storeSettings(...)`), validate `settings.ipLogging`.
   - Allowed values: `anonymous`, `truncated`, `full`.
   - If invalid (including null/undefined), `logger.error` or `logger.warn` and set `settings.ipLogging = 'anonymous'`.
2. Consider making `anonymizeIp()` defensive:
   - Use an explicit `switch (mode)` with a `default` that returns `'ANONYMOUS'` (privacy-safe) or throws in dev/test.
3. Add/adjust a backend test asserting invalid `ipLogging` values are rejected or normalized to `'anonymous'`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

JohnMcLear and others added 8 commits April 19, 2026 10:23
Second of five GDPR PRs (#6701). Audit identifies four log-sites that
leak IPs despite disableIPlogging=true, proposes a tri-state ipLogging
setting with a back-compat shim, and specifies a doc/privacy.md that
documents Etherpad's actual IP handling.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
7 TDD-structured tasks: anonymizeIp helper + unit tests, tri-state
ipLogging setting with disableIPlogging deprecation shim, wiring
through 5 leaking log sites, clientVars.clientIp removal, access-log
integration test, doc/privacy.md, and PR handoff.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes four leaks where disableIPlogging was silently ignored
(rate-limit warn, both auth-log calls in webaccess, import/export
rate-limit warn) and normalises the four that did honour the flag
onto the new ipLogging tri-state via the shared helper.
Server side: remove the literal '127.0.0.1' assignments from both
clientVars and collab_client_vars. Type side: drop clientIp from
ClientVarPayload and ServerVar. pad.getClientIp now returns the same
'127.0.0.1' literal as a plugin-compat shim (pad_utils.uniqueId still
uses it as a prefix).
Qodo review:
- settings.ipLogging is loaded as a trusted union but nothing enforced
  the shape. An unknown value (e.g. a typo or null) silently fell
  through to anonymizeIp's "truncated" branch and emitted partially
  redacted IPs. Fall back to "anonymous" with a WARN at load time.
- New regression test scans the four known log-sites for raw
  req.ip / socket.request.ip / request.ip inside logger calls that
  don't wrap through anonymizeIp / logIp, so a future edit that
  re-introduces a raw IP fails CI.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant