This is an automated email from the ASF dual-hosted git repository.

pjfanning pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/pekko-http.git


The following commit(s) were added to refs/heads/main by this push:
     new c428fede4 Add a draft threat model and wire it for discoverability 
(#1242)
c428fede4 is described below

commit c428fede4a625a68bdb6d9fa7a989f0a526ef06d
Author: Jarek Potiuk <[email protected]>
AuthorDate: Thu Sep 10 09:48:01 2026 +0200

    Add a draft threat model and wire it for discoverability (#1242)
    
    * Add a draft threat model and wire it for discoverability
    
    ### Motivation
    The Pekko PMC asked the ASF Security team for a draft threat model to 
refine,
    as preparation for a Claude security scan. This is the companion to the same
    change in apache/pekko.
    
    docs/src/main/paradox/security.md already has a "Security model" section, 
and
    it makes the most important statement in this document: applications should 
not
    be exposed to the public internet directly, and DoS resistance is claimed 
only
    as "pretty well under most known" attacks. But that is three sentences, and 
the
    quantitative envelope that actually bounds untrusted input -- the parsing 
limits
    in http-core's reference.conf -- is not connected to it anywhere.
    
    Separately, the AGENTS.md -> SECURITY.md chain a scanning agent follows to
    locate a project's model does not resolve: there is no SECURITY.md in the 
repo.
    
    ### Modification
    - THREAT_MODEL.md: a v0 draft following the Scovetta rubric. §5a collects 
the
      shipped parsing limits, timeouts and CORS defaults as the model's 
quantitative
      spine; §8 states the six default-on properties they underwrite.
    - SECURITY.md: reporting policy pointing at [email protected], plus the 
three
      points that catch most reporters.
    - AGENTS.md: a Security section pointing at both.
    
    Nothing security.md asserts has been dropped or weakened; §15 back-maps each
    existing statement to the section that now carries it.
    
    ### Result
    The chain AGENTS.md -> SECURITY.md -> THREAT_MODEL.md resolves on main, and
    triagers have a citable document with a closed set of dispositions (§13).
    
    §14 holds 10 questions, each stated as a proposed answer. The two worth 
reading
    first are Q1 (where exactly is the DoS line, given security.md's 
deliberately
    graded claim?) and Q2 (http-cors ships allowed-origins = "*" with
    allow-credentials = yes, which per its own reference.conf echoes the request
    Origin -- deliberate, or should the default change?).
    
    The document is not ready to be treated as canonical until those are 
answered.
    
    ### Tests
    Not run - docs only
    
    ### References
    None - requested by the Pekko PMC chair on the ASF security scan thread
    
    * Update THREAT_MODEL.md
    
    * Answer Q1 and Q2, and record the defaults posture as §5b
    
    Motivation:
    The draft threat model left ten questions open in §14. Two of them were not
    lookups but rulings only the PMC could make, and until they were settled a
    triager had no line to apply: Q1, the boundary of the "behaves pretty well
    under most known DoS attacks" claim, and Q2, the CORS defaults. Separately,
    the model had no statement of the project's standing position on 
configuration
    defaults, so every "this default should be stricter" report had to be argued
    from scratch.
    
    Modification:
    - §14 Q1 answered: the DoS line is content vs. volume. A single request 
within
      every §5a limit that provokes super-linear CPU or memory is VALID; a 
finding
      needing a limit raised is OUT-OF-MODEL: non-default-build; one depending 
on
      request volume is BY-DESIGN: property-disclaimed. Propagated to §4, §5, 
§5a,
      §7, §8, §9, §11a and §13.
    - New §5b, "Security posture: hardening, not secure-by-default", mirroring
      apache/pekko#3478 §5b: defaults are compatibility choices, a request to
      tighten one is a change request not a vulnerability, proposals belong on 
the
      development list, and an implementation that does not do what it 
documents is
      a defect this project fixes.
    - §14 Q2 answered from §5b: the CORS pair is a compatibility default, 
inherited
      with the code donated by Lomig Mégard (legal/CorsNotice.txt). A request to
      change it is BY-DESIGN: default-configuration; a cors() directive that 
admits
      an origin its configuration should have rejected remains in scope.
    - New §13 disposition BY-DESIGN: default-configuration, disambiguated from
      OUT-OF-MODEL: non-default-build (a real defect reachable only off-default,
      versus no defect at all).
    - SECURITY.md states both rulings for reporters, and closes on what the 
project
      does want: an implementation that does not match its documentation.
    
    Result:
    Resource exhaustion and default-configuration reports now route to exactly 
one
    §13 disposition instead of being judgment calls. Four of the ten §14 
questions
    are closed; the six remaining are confirm-or-correct. Provenance moves from
    17 documented / 0 maintainer / 15 inferred to 17 / 6 / 13.
    
    Tests:
    Not run - docs only
    
    References:
    Refs #1242
    
    * Answer Q4-Q8, resolve Q9 against the source, correct the client-IP claim
    
    Motivation:
    Six of the ten §14 questions were still open, and two of them rested on
    statements that the source contradicts. Q4 asserted that Pekko HTTP "neither
    parses nor trusts forwarding headers", which is not what extractClientIP 
does.
    Q9 held §5's negative claims as the document's last uncited assertions, and 
the
    equivalent section in apache/pekko#3478 turned out to be wrong on review, so
    asserting rather than checking them was not good enough here either.
    
    Modification:
    - Q4 answered, and its stated basis corrected: extractClientIP resolves
      X-Forwarded-For (first address) -> X-Real-Ip -> the remoteAddress 
attribute
      (MiscDirectives.scala:142-145), so forwarding headers are parsed, just 
never
      implicitly. The spoofability is documented at the directive and answered 
by
      extractDirectClientIP (#1219), which reads the attribute alone. 
Disposition is
      unchanged: BY-DESIGN: property-disclaimed, with a defect in
      extractDirectClientIP being VALID. Propagated to §5, §6, §9, §10.5, §11, 
§11a.
    - Q5, Q6, Q7 and Q8 answered as proposed: the verify/provideVerify split, 
the §2
      module in/out split, the non-goals and adversary split, and TLS cipher
      selection as a deployment property. Q8 additionally records that 
in-process
      termination is supported while the fronted posture is what the docs 
recommend.
    - Q9 resolved by scanning the main sources of http-core, http, parsing,
      http-caching and http-cors: no addShutdownHook, 
ProcessBuilder/Runtime.exec,
      Signal/SignalHandler, file-writing API, System.setProperty/Security.*, or 
bind
      outside the public Http().bind* entry points. §5 now cites the scan, and
      records the inherited caveat that the ActorSystem registers shutdown hooks
      Pekko HTTP does not.
    
    Result:
    No claim in the document is inferred any more; provenance moves from
    17 documented / 6 maintainer / 13 inferred to 20 / 24 / 0. Q10 (coexistence 
with
    security.md) is the only question left open.
    
    Tests:
    Not run - docs only
    
    References:
    Refs #1242
    
    * Answer Q9: Pekko HTTP registers no shutdown hook of its own
    
    Motivation:
    Q9 was resolved against the source but left the disposition open: §5's scan
    showed Pekko HTTP adds no JVM shutdown hook, while the ActorSystem it runs 
on
    does. Whether to state that boundary here or defer the topic to the 
companion
    model needed a ruling, and the distinction is easy to misattribute in 
triage.
    
    Modification:
    - Q9 answered: highlight the ActorSystem's hooks in §5 so integrators are 
not
      surprised, but the claim this document makes is that Pekko HTTP registers
      none of its own.
    - Promoted "Registers no JVM shutdown hook" from a trailing clause on the
      signal-handler bullet to its own §5 claim, so the load-bearing statement 
is
      stated directly rather than implied.
    - Sharpened the §5 caveat to separate the two readings: "a Pekko HTTP 
process
      has no shutdown hook" is false, "Pekko HTTP registers no shutdown hook" is
      true and is what this section asserts.
    - New §11a non-finding: a report that the process registers shutdown hooks 
is
      OUT-OF-MODEL: unsupported-component, since the hooks are 
CoordinatedShutdown's
      and, with remoting enabled, Artery's.
    
    Result:
    Q10 (coexistence with security.md) is the only question left open. 
Provenance is
    20 documented / 26 maintainer / 0 inferred.
    
    Tests:
    Not run - docs only
    
    References:
    Refs #1242
    
    * Answer Q10: three documents, each canonical for one thing
    
    Motivation:
    Q10 was the last open question: which document is canonical for what, now 
that
    THREAT_MODEL.md, SECURITY.md and docs/src/main/paradox/security.md all carry
    security information. apache/pekko#3478 settled the same question for the
    companion project, and following its split keeps the two models consistent 
for
    anyone triaging across both.
    
    Modification:
    - Q10 answered with the three-document table from apache/pekko#3478: 
SECURITY.md
      is canonical for the reporting policy, THREAT_MODEL.md for scope and 
triage,
      and docs/src/main/paradox/security.md for announcements and the docs-site
      index. Every other document links rather than restates.
    - docs/src/main/paradox/security.md gains links to SECURITY.md and
      THREAT_MODEL.md, and its reporting paragraph now names [email protected]
      rather than "our private security mailing list", which does not exist. 
This
      mirrors the equivalent change in apache/pekko#3478.
    - Corrected the draft's own proposal, which suggested reducing the "Security
      model" section of security.md to a pointer. It is kept: §4 quotes it as 
the
      documented source of the "should not be exposed to the public internet
      directly" posture and §15 back-maps four claims to it, so reducing it 
would
      delete the evidence this model is built on.
    
    Result:
    All ten §14 questions are answered. One item is referred rather than 
settled, as
    the ruling requires: security.md carries an upstream-coordination sentence 
about
    sharing reports with the Lightbend Akka team that SECURITY.md does not, and 
a
    reporting statement is promoted verbatim or dropped by maintainer decision, 
never
    silently moved. Provenance is 20 documented / 27 maintainer / 0 inferred.
    
    Tests:
    Not run - docs only
    
    References:
    Refs #1242
    
    * Correct two §5/§9 claims against the source and answer Q3
    
    Motivation:
    Maintainer review found two claims that do not hold on main and one
    internal inconsistency:
    - §5 claimed Pekko HTTP writes no files, but fileUploadAll creates temp
      files and storeUploadedFile(s) writes entity bytes to an
      application-chosen destination (FileUploadDirectives.scala:178).
    - §9 and §14 Q3 described safeDirectoryChildPath as containing
      traversal, but its canonical-path check compares strings, so a
      symlink resolving into a sibling directory that shares the served
      root as a string prefix escapes it (fix in flight in #1218).
    - The status line said both "Q1-Q8 answered" and "all ten answered"
      while Q3 still ended in an open question, and the pinned commit was
      the PR's own first commit rather than the main commit reviewed.
    
    Modification:
    Restate the §5 file-system claim with the upload-directive carve-out
    and correct Q9 accordingly. Answer Q3 as a correction: the escape is
    VALID under §5b.4 and fixed by #1218; update §9 and the §15 back-map to
    match. Note in §12 that #1217 would invalidate the shutdown-hook claim
    on merge. Fix the status line, the tag tally, and the commit pin
    (444d939 -> 85d7243, the main commit the branch is based on).
    
    Result:
    Every §5 negative claim matches the source at the pinned commit, Q3 is
    answered consistently with the "all ten answered" status, and the two
    in-flight PRs that touch the model's claims (#1217, #1218) are
    cross-linked.
    
    Tests:
    Not run - docs only
    
    References:
    Refs #1218, Refs #1217
    
    * Update the §12 note on #1217: reworked to a CoordinatedShutdown task
    
    Motivation:
    §12 flagged #1217's raw JVM shutdown hook as invalidating the §5
    "registers no shutdown hook" claim on merge. That PR has since been
    reworked to register its temp-file cleanup as a CoordinatedShutdown
    task on the actor system instead, so no §5 claim is affected.
    
    Modification:
    Restate the §12 bullet as a recorded near-miss rather than a pending
    invalidation.
    
    Result:
    §12 matches the current state of #1217 and the §5/§11a claims stand.
    
    Tests:
    Not run - docs only
    
    References:
    Refs #1217
    
    * Fold the reworked #1217 and #1218 into §5, §9 and Q3
    
    Motivation:
    Both in-flight PRs the model references changed shape after review.
    #1218 gained a documented platform caveat - File.getCanonicalPath does
    not resolve NTFS symbolic links or junctions on Windows, so the
    link-escape class stays open there - and now rejects path segments that
    no file-system path may contain instead of erroring. #1217 replaced the
    per-file deleteOnExit with one temp directory per actor system removed
    by a CoordinatedShutdown task. Q3's answer claimed symlink escapes are
    rejected "whatever its target is named", which overclaims on Windows.
    
    Modification:
    Scope the Q3 and §9 symlink-rejection claims to platforms where
    canonicalization resolves links, record the Windows residual and the
    toRealPath follow-up, note the invalid-segment hardening, and update
    the §5 upload-directive note to describe #1217's per-system directory
    and CoordinatedShutdown cleanup.
    
    Result:
    The model's containment and file-writing claims match what #1217 and
    #1218 actually implement, on every platform they address.
    
    Tests:
    Not run - docs only
    
    References:
    Refs #1217, Refs #1218
    
    * Record the decoding limits that bound decompression bombs
    
    Motivation:
    Review of the threat model pointed out that §9 lists decompression bombs
    as an attack class "left to the caller", which is not accurate: the
    routing block ships two limits that bound a decoded entity, and the
    decoding directives apply them without the caller doing anything.
    
    Modification:
    Add `routing.decode-max-bytes-per-chunk` and `routing.decode-max-size` to
    the §5a limits table, and amend its intro and citation to cover the
    second reference.conf they live in. Rewrite the §9 bullet to state what
    the directives bound, cited to CodingDirectives.scala:93-102, and narrow
    what remains the caller's: decoding outside the directives, and raising
    decode-max-size to infinite.
    
    Result:
    §5a lists every shipped limit that bounds an entity, decompression
    included, and §9 no longer disclaims a control the project provides.
    
    Tests:
    Not run - docs only
    
    References:
    Refs #1242
    
    * Re-pin the model to the rebased base and correct P2 against the render 
path
    
    Motivation:
    Rebasing the branch moved its base from `85d7243` to `6740cbd`, twenty-four
    commits later, so the document's "written against" pin no longer named a
    commit on the branch. Several of those commits touched claims the document
    makes, and one of them falsified a §8 property as stated.
    
    P2 ("response splitting is blocked") was asserted from the two
    `illegal-response-header-*-processing-mode` defaults alone, without
    walking the path those settings govern. Walking it finds the guard lived
    in a single `~~(HttpHeader)` overload, so chunked-response trailers and
    chunk extensions rendered around it (#1256), it tested CR and LF but not
    NUL (#1260), and the HTTP/2 header path had no equivalent check, so the
    mitigation an application relies on under HTTP/1.1 disappeared on upgrade
    (#1258). All three are fixed at the new base. #1217 and #1218, which the
    document tracked as in flight, have also landed.
    
    Modification:
    Re-pin to `6740cbd`. Restate P2 as a claim about the merged enforcement
    path — naming the trailer, chunk-extension, NUL and HTTP/2 gaps and the
    single `Rendering.isIllegalHeaderChar` predicate that now holds the rule
    — and record how it came to be stated that precisely. Update §5 and §12
    for #1217 merging in its reworked `CoordinatedShutdown` form, re-checked
    against the merged code: no `addShutdownHook` outside a comment saying
    why one is not used. Make §5b.4's three examples concrete, two of them
    having stopped being hypothetical during review. Add to the §5a CORS
    ruling that it governs the default and never the enforcement, citing
    #1262, where `validateOrigins` accepted a request if any origin matched
    while the response echoed every origin it was given.
    
    Result:
    The pin names the commit the claims are verified against, P2 describes
    what the code does rather than what two settings imply, and the CORS
    section distinguishes a permissive default from a restrictive setting
    that fails to restrict.
    
    Tests:
    Not run - docs only
    
    References:
    Refs #1242, #1256, #1258, #1260, #1262, #1217, #1218
    
    * Account for the rest of the fixes merged since the pin, and fix four 
citations
    
    Motivation:
    Re-pinning caught #1217, #1218 and the three response-splitting fixes,
    but six more merged between `85d7243` and `6740cbd` and the document
    accounts for none of them. Two matter: P1 was asserted the same way P2
    was — from the §5a table, which records what each limit is meant to
    bound rather than what the code does when one is reached — and three of
    those bounds did not hold. Separately, four source citations no longer
    point at the code they name.
    
    Modification:
    Restate P1 as a claim about enforcement and add the note recording how it
    came to be stated that way: `max-chunk-count` reported the limit without
    stopping the parse (#1220), `max-header-count` skipped the branch that
    merges repeated Connection headers (#1255), and HTTP/2 connection-level
    buffer accounting never decremented on a discarded buffer, stalling every
    stream on the connection once the leak passed half the configured size
    (#1259). Give the §9 smuggling bullet the framing decision Pekko HTTP
    does own, citing #1267. Add the three HTTP/2 buffer bounds to §5a and to
    the §15 back-map, together with the decoding limits.
    
    Citations: `Http.scala` no longer has public `bind`/`bindAndHandle`
    methods, so §5 now names `newServerAt` and the `ServerBuilder` it
    returns; `FileAndResourceDirectives.scala:229-274` moved to `246-296`;
    `CorsSettingsImpl.scala:64` is `63`. §2 listed `http2-tests` as the
    in-model HTTP/2 module while the same table marks it out of model — the
    engine is `http-core`.
    
    Result:
    Every fix merged since the pinned commit is either reflected in a claim
    or deliberately not: #1239 (no body on an HTTP/2 HEAD response) and #1261
    (ignoring the reserved bit of a stream identifier) are conformance fixes
    that bear on no claim the document makes. Provenance is 20 documented /
    31 maintainer / 0 inferred.
    
    Tests:
    Not run - docs only
    
    References:
    Refs #1242, #1220, #1255, #1259, #1267
    
    * Close three gaps the open PRs exposed in the model
    
    Motivation:
    Reviewing the open PRs from the last three weeks against the document
    turned up three claims that are wrong or missing today, independently of
    whether any of those PRs merge.
    
    Modification:
    P1 claims inbound messages are bounded by the §5a limits, and for HTTP/2
    frames nothing bounds them: the frame parser reads the 24-bit length
    field and takes that many bytes, up to 16 MiB - 1, before HPACK decoding
    and before the entity is assembled, so none of the three HTTP/2 buffer
    bounds apply. State the gap under P1, name #1264 as the fix in flight,
    and rule an oversized-frame report VALID against P1 rather than a §12
    model gap in the meantime.
    
    The `frame-type-throttle` block was absent from the whole document, even
    though it ships on by default charging RST_STREAM at 100/s and is the
    project's HTTP/2 Rapid Reset mitigation (CVE-2023-44487). Add it to §5a
    and to the §15 back-map, and restate P6: `max-concurrent-streams` alone
    bounds concurrency and not work, because a reset frees the slot at once.
    
    §9 claimed traversal containment for "file-serving directives" without
    qualification. Three tiers, checked against the source: `getFromDirectory`
    and `listDirectoryContents` (and the browseable pair built on them) get
    `safeDirectoryChildPath`, segment filter plus canonical containment;
    `getFromResourceDirectory` gets `safeJoinPaths` alone, coherent since a
    class-loader resource name has no canonical form; `getFromFile` and
    `getFromResource` get neither. Scope §14 Q3's answer to the first tier
    and name `getFromResource` in the §11 misuse list, where only
    `getFromFile` was listed.
    
    Result:
    The containment claim matches what each directive implements, the Rapid
    Reset mitigation is claimed where a reader of §8 will find it, and the
    one bound P1 asserts but does not yet have is written down. Provenance is
    20 documented / 32 maintainer / 0 inferred.
    
    Tests:
    Not run - docs only
    
    References:
    Refs #1242, #1264, #1263
    
    ---------
    
    Co-authored-by: PJ Fanning <[email protected]>
---
 AGENTS.md                         |   6 +
 SECURITY.md                       |  67 +++++++
 THREAT_MODEL.md                   | 409 ++++++++++++++++++++++++++++++++++++++
 docs/src/main/paradox/security.md |   6 +-
 4 files changed, 487 insertions(+), 1 deletion(-)

diff --git a/AGENTS.md b/AGENTS.md
index 09388d13a..0038cc39f 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -230,3 +230,9 @@ Fixes #1234, Refs #1234, or None - <short context>
 - Never omit `References`.
 - Use `Refs #...`, `Fixes #...`, or `None - <short context>`.
 - Do not add `Co-authored-by` or AI-assistant trailers to commits or PR 
descriptions.
+
+## Security
+
+- Read [`SECURITY.md`](SECURITY.md) before reporting or acting on a security 
issue.
+- Classify security findings against the threat model it links,
+  [`THREAT_MODEL.md`](THREAT_MODEL.md); §11a lists recurring false positives.
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 000000000..adca613c3
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,67 @@
+# Security Policy
+
+## Reporting a Vulnerability
+
+**Do not report security vulnerabilities through public GitHub issues, pull
+requests, or the mailing lists.**
+
+Report them privately to the Apache Security team:
+
+    [email protected]
+
+Apache Pekko does not operate a separate project security list; reports go to
+the foundation-wide address above, which routes to the Pekko PMC.
+
+Please follow the [guidelines laid down by the Apache Security
+team](https://www.apache.org/security/).
+
+To receive security announcements, subscribe to the [Apache Announce Mailing
+List](https://lists.apache.org/[email protected]).
+
+## Security Model
+
+Before reporting, please read Apache Pekko HTTP's threat model:
+
+[THREAT_MODEL.md](THREAT_MODEL.md)
+
+It states what Pekko HTTP treats as a vulnerability and what it does not — the
+documented parsing limits that bound untrusted input, which configuration
+defaults change the security envelope, and which properties are deliberately
+left to the application. Reports that fall outside the model will be closed
+citing the relevant section, so checking first will save you time.
+
+Three points catch most reporters:
+
+- **Pekko HTTP is not meant to face the public internet unaided.** The project
+  recommends fronting it with an enterprise-grade routing solution or a load
+  balancer. For denial of service the model draws an explicit line: a **single
+  request within every documented limit** that causes disproportionate CPU or
+  memory use is a vulnerability, and we want that report. Resource exhaustion
+  that depends on request **volume** — connection floods, slow-loris at scale —
+  is the fronting proxy's job and will be closed as by-design. Load-generator
+  output is not a finding. See §5a for the limits and §14 Q1 for the ruling.
+- **Pekko HTTP is a toolkit, not a security system.** It provides no
+  authentication policy, no authorization model, no CSRF protection and no
+  output encoding. The security directives route credentials to a verifier the
+  application supplies. See §9.
+- **Requests rejected for exceeding a documented limit are the limits 
working**,
+  not a bug. The limits are listed in §5a.
+- **Configuration defaults are compatibility choices, not security claims.** 
Pekko
+  HTTP inherits a large deployment base from Akka HTTP, and tightening a 
shipped
+  default breaks working deployments on upgrade. A report that a default 
*should*
+  be stricter is a change request, not a vulnerability, and will be closed as
+  by-design — but it is genuinely welcome on the development list, where the 
PMC
+  will weigh it on its merits. You are free to strengthen any of these 
settings in
+  your own configuration, and §10 says which ones matter most. See §5b.
+
+**What we do want.** The flip side of the above is the report this project 
values
+most: **an implementation that does not do what it is documented to do.** If a
+parsing limit fails to bound what it claims to bound, if a control that is 
switched
+on can be bypassed, if a containment check can be walked around — that is a 
defect,
+it is in scope, and we will fix it. The defaults debate is about which value 
ships;
+it never excuses a mechanism that does not work.
+
+## Further Security Documentation
+
+- [Pekko HTTP security 
announcements](https://pekko.apache.org/docs/pekko-http/current/security.html)
+- [Apache Pekko threat 
model](https://github.com/apache/pekko/blob/main/THREAT_MODEL.md) — the actor, 
stream, remoting and cluster layers this project builds on
diff --git a/THREAT_MODEL.md b/THREAT_MODEL.md
new file mode 100644
index 000000000..0e83901b8
--- /dev/null
+++ b/THREAT_MODEL.md
@@ -0,0 +1,409 @@
+# Apache Pekko HTTP — Threat Model
+
+**Status:** Reviewed by a Pekko maintainer. **All ten questions in §14 are 
answered** and are settled model, and §5b records the project's standing 
position on configuration defaults. One item is referred rather than settled: 
whether the upstream-coordination sentence in `security.md` should be promoted 
into `SECURITY.md` (§14 Q10). No claim in this document is now uncited: every 
assertion is either cited to Pekko HTTP's own source and configuration, or 
stated by a maintainer.
+
+| | |
+| --- | --- |
+| **Project** | Apache Pekko HTTP |
+| **Written against** | commit `6740cbd`, `main` |
+| **Date** | 2026-08-27 |
+| **Authors** | ASF Security team, at the request of the Pekko PMC |
+| **Version binding** | Versioned alongside the project. A report against 
version *N* is triaged against the model as it stood at *N*, not at `main`. |
+| **Reporting** | Findings that violate a §8 property should be reported per 
[`SECURITY.md`](SECURITY.md). Findings under §3 or §9 will be closed citing 
this document. |
+| **Companion model** | Pekko HTTP is built on Pekko Streams and Actors. The 
actor, remoting and cluster layers are modeled in [`apache/pekko`'s 
`THREAT_MODEL.md`](https://github.com/apache/pekko/blob/main/THREAT_MODEL.md); 
this document does not restate them. |
+
+**Provenance legend.**
+*(documented)* — stated in Pekko HTTP's own docs or `reference.conf` comments, 
cited.
+*(maintainer)* — stated by a Pekko maintainer in review of this document.
+*(inferred)* — reasoned from code or config defaults, **not yet confirmed**; 
each has a matching question in §14.
+
+**Confidence:** 20 documented / 32 maintainer / 0 inferred — counting inline 
tags only. The §5a limits table and the §15 back-map carry a further ~40 
documented facts under a single collective citation each, so the document is 
more evidence-backed than the bare ratio suggests. **Nothing in the document is 
inferred any more.** Q1-Q9 were answered by a maintainer in review; Q3, Q5 and 
Q9 were resolved against the source first, the last of these replacing §5's 
negative claims with a cited s [...]
+
+Apache Pekko HTTP is a Scala/Java toolkit for building HTTP-based services and 
clients on top of Pekko Streams. It provides a full HTTP/1.1 and HTTP/2 
implementation — parsing, connection management, marshalling, and a routing DSL 
of composable "directives" — as an **embeddable library**, not a standalone 
server. The application supplies the routes, the authentication, and the 
deployment.
+
+---
+
+## §2 Scope and intended use
+
+Pekko HTTP is a library the application embeds. There is no Pekko HTTP daemon 
to secure independently of the service built on it.
+
+Caller roles:
+
+- **The embedding application** — fully trusted. Defines routes, supplies 
handlers, chooses configuration.
+- **The operator/deployer** — trusted for the instance. Chooses what sits in 
front of the service (see §4), TLS termination, and limits.
+- **The HTTP client** — **untrusted**. This is the adversary the model is 
mostly about.
+
+### Component families
+
+| Family | Modules | Entry point | In model |
+| --- | --- | --- | --- |
+| Core protocol | `http-core`, `parsing` | Wire bytes → `HttpRequest` / 
`HttpResponse` | **yes — primary surface** |
+| HTTP/2 | `http-core` (`impl/engine/http2`) | HTTP/2 framing, HPACK, streams 
| **yes** |
+| Routing DSL | `http` | `Route`, directives, rejection/exception handling | 
**yes** |
+| Marshalling | `http-marshallers-scala`, `http-marshallers-java` | JSON/XML 
entity conversion | **yes** |
+| CORS | `http-cors` | `cors()` directive | **yes — see §5a** |
+| Caching | `http-caching` | response cache directives | **yes** |
+| Test kits | `http-testkit`, `http-testkit-munit`, `http-tests`, 
`http-compatibility-tests`, `http2-tests` | — | **no** — §3 |
+| Benchmarks | `http-bench-jmh` | — | **no** — §3 |
+| Lint / build / docs | `http-scalafix`, `docs`, `project`, `scripts`, `legal` 
| — | **no** — §3 |
+
+*(maintainer — the in/out split is confirmed by the Pekko maintainers; see §14 
Q6)*
+
+---
+
+## §3 Out of scope (explicit non-goals)
+
+- **Test kits, benchmarks, scalafix rules, build tooling and documentation 
sources.** A finding in `http-bench-jmh` or any `*-tests` module is 
`OUT-OF-MODEL: unsupported-component`. *(maintainer — §14 Q6)*
+- **Pekko HTTP is not a WAF, and not an edge-hardened server.** The 
documentation says so plainly: applications *"should not be exposed to the 
public internet directly"* and an *"enterprise grade routing solution"* or a 
load balancer such as Apache HTTP Server or Nginx *"would be safer"* 
*(documented — `security.md`)*. See §4.
+- **Pekko HTTP is not an authentication or authorization system.** It ships 
`authenticateBasic`, `authenticateOAuth2` and `authorize` directives, but these 
are *plumbing*: the credential check is a function the application supplies. 
Pekko HTTP has no user store, no session model, and no policy engine. 
*(maintainer — §14 Q7)*
+- **The actor, stream, remoting and cluster layers** are out of scope here and 
covered by `apache/pekko`'s threat model.
+- **Attackers who already control the embedding process** are out of scope. 
*(maintainer — §14 Q7)*
+
+---
+
+## §4 Trust boundaries and data flow
+
+**The trust boundary is the inbound HTTP request.** Everything derived from 
wire bytes — request line, headers, cookies, entity, HTTP/2 frames — is 
attacker-controlled until the application validates it.
+
+Pekko HTTP's documented posture is unusual and important enough to quote in 
full:
+
+> "Pekko HTTP-based applications should not be exposed to the public internet 
directly. We believe Pekko HTTP behaves pretty well under most known Denial of 
Service attacks, but if you want the best security, you should use an 
enterprise grade routing solution. Even using a load balancing solution like an 
up-to-date version of Apache HTTP Server or Nginx would be safer than exposing 
Pekko HTTP-based applications directly to the public internet."
+> — *(documented — `security.md`, "Security model")*
+
+Read carefully, this makes a **graded** claim rather than a binary one: Pekko 
HTTP asserts it *"behaves pretty well under most known"* DoS attacks — not that 
it is DoS-proof, and not that DoS is out of scope. That hedge was the single 
most consequential ambiguity in this model for triage; §14 Q1 has now resolved 
it into the content-vs-volume line, which is the rule triage actually applies.
+
+### Reachability preconditions per family
+
+- **Core protocol / HTTP/2** — reachable from raw wire bytes. The strongest 
in-model surface: a parser defect here needs no application cooperation.
+- **Routing DSL** — reachable from a request that the application's own routes 
expose. A finding must name the directive and show a route shape a reasonable 
application would write.
+- **Marshalling** — reachable from an entity body **only where the application 
has bound that marshaller to a route**. Findings in the underlying JSON/XML 
library belong to that library.
+- **CORS** — reachable only where the application has installed the `cors()` 
directive. It is opt-in, not on by default. See §5a.
+- **Caching** — reachable only where the application has installed a caching 
directive; cache-key correctness is the sharp edge.
+
+---
+
+## §5 Assumptions about the environment
+
+- **Runtime.** A conformant JVM. Pekko HTTP does not defend against a hostile 
JVM or in-process attacker. *(maintainer — §14 Q7)*
+- **Fronting infrastructure.** The documented expectation is that something 
sits in front in production *(documented — `security.md`)*. Per §14 Q1 this is 
load-bearing for *volume* only: the proxy is relied on for flood and slow-loris 
defence, not for bounding a single request, which is P1's job.
+- **TLS.** Pekko HTTP can terminate TLS itself (`HttpsConnectionContext`) and 
this is supported, though the documented recommendation to front the service 
(§4) means termination is commonly the proxy's job in production. Cipher and 
protocol selection come from the JSSE context the application supplies — Pekko 
HTTP pins nothing and overrides no JDK default, so cipher strength is a 
deployment property. *(maintainer — §14 Q8)*
+- **Client IP.** `remote-address-attribute` ships `off` *(documented — 
`reference.conf`)*. When on, the attribute reflects the **socket** peer, which 
behind a proxy is the proxy; forwarding headers never feed it. Header-derived 
client IP is opt-in at the call site: `extractClientIP` reads `X-Forwarded-For` 
/ `X-Real-Ip` and is therefore client-controllable, while 
`extractDirectClientIP` reads the attribute alone and is not. Choosing between 
them is the application's decision (§14 Q4). *( [...]
+
+### What Pekko HTTP does not do to its host
+
+Negative claims, rarely written down and therefore verified against the source 
rather than asserted. The scan below covers the main sources of `http-core`, 
`http`, `parsing`, `http-caching` and `http-cors` *(documented — source scan, 
§14 Q9)*:
+
+- **Binds no port until the application asks for one.** Binding is reachable 
only through `Http().newServerAt(...)` (`Http.scala:156`) and the 
`ServerBuilder` it returns — `bind`, `bindSync`, `bindFlow`, 
`connectionSource`; the implementations behind them are `private[http]` 
(`Http.scala:179-292`). Nothing binds at class or extension initialization.
+- **Installs no signal handlers and spawns no child processes.** No 
`sun.misc.Signal`/`SignalHandler`, `ProcessBuilder` or `Runtime.exec` in the 
main sources.
+- **Registers no JVM shutdown hook.** There is no `addShutdownHook` anywhere 
in Pekko HTTP's main sources. Any hook an integrator observes comes from the 
actor system, not from here — see the caveat below.
+- **Touches the file system only through directives the application 
installs.** The disk-serving directives (`getFromFile`, `getFromDirectory`) 
read. The upload directives **write**: `storeUploadedFile(s)` streams entity 
bytes to a destination the application's function chooses, and `fileUploadAll` 
buffers each part into a `Files.createTempFile` temp file registered with 
`deleteOnExit` (since [#1217](https://github.com/apache/pekko-http/pull/1217) 
landed, those temp files go into one dir [...]
+- **Does not mutate process-global state at initialization** — no 
`System.setProperty`, `Security.setProperty`, `Security.addProvider` or 
`setDefault(...)`.
+
+**One inherited caveat, highlighted because it is easy to misattribute.** The 
claims above cover Pekko HTTP's own modules, not the `ActorSystem` it runs on. 
`apache/pekko` *does* register JVM shutdown hooks — one in 
`CoordinatedShutdown`, and a second in Artery when remoting is enabled — so an 
integrator running a Pekko HTTP service **will** observe shutdown hooks in the 
process. They arrive with the actor system and are modeled in the companion 
document. **Pekko HTTP itself adds none**, [...]
+
+---
+
+## §5a Configuration variants that change the security envelope
+
+Pekko HTTP's resistance to malformed and abusive input is almost entirely a 
function of `pekko.http.server.parsing.*`, with two entries under 
`pekko.http.routing.*` bounding what the parsing limits cannot see — the size 
of an entity *after* it has been decompressed. These are the **documented, 
shipped** limits *(all documented — 
`http-core/src/main/resources/reference.conf`, and 
`http/src/main/resources/reference.conf` for the two `routing` entries)*:
+
+| Setting | Default | What it bounds |
+| --- | --- | --- |
+| `max-uri-length` | `2k` | Request-line URI |
+| `max-method-length` | `16` | Method token |
+| `max-header-name-length` | `64` | Single header name |
+| `max-header-value-length` | `8k` | Single header value |
+| `max-header-count` | `64` | Headers per message |
+| `max-content-length` | `8m` (server) | Entity size |
+| `max-chunk-size` | `1m` | Single chunk |
+| `max-chunk-count` | `100000` | Chunks per message |
+| `max-chunk-ext-length` | `256` | Chunk extension |
+| `max-comment-parsing-depth` | `5` | Nested comment recursion |
+| `max-to-strict-bytes` | `8m` | `toStrict` materialization |
+| `max-concurrent-streams` | `256` | HTTP/2 concurrent streams |
+| `max-header-list-size` | `64 KiB` | HTTP/2 decompressed header list, **and** 
the accumulated HEADERS + CONTINUATION fragments for one header block |
+| `incoming-connection-level-buffer-size` | `10 MB` | HTTP/2 incoming data 
buffered across one connection |
+| `incoming-stream-level-buffer-size` | `512kB` | HTTP/2 incoming data 
buffered for one stream |
+| `outgoing-control-frame-buffer-size` | `1024` | HTTP/2 outgoing control 
frames queued before the connection fails |
+| `frame-type-throttle` | `frame-types = ["reset"]`, `cost = 100`, `burst = 
100`, `interval = 1 s` | HTTP/2 frames charged against a rate limit — 
`RST_STREAM` by default, mitigating HTTP/2 Rapid Reset (CVE-2023-44487) — 
**secure default** |
+| `max-connections` | `1024` | Server connections |
+| `pipelining-limit` | `1` | In-flight pipelined requests |
+| `idle-timeout` | `60 s` | Connection idle |
+| `request-timeout` | `20 s` | Per-request handling |
+| `uri-parsing-mode` | `strict` | URI leniency |
+| `cookie-parsing-mode` | `rfc6265` | Cookie leniency |
+| `verbose-error-messages` | `off` | Whether parse errors leak detail to the 
client — **secure default** |
+| `illegal-response-header-name-processing-mode` | `error` | Blocks 
response-splitting via header names — **secure default** |
+| `illegal-response-header-value-processing-mode` | `error` | Blocks 
response-splitting via header values — **secure default** |
+| `server-header` | `pekko-http/${version}` | Advertises product and version |
+| `remote-address-attribute` | `off` | Exposes socket peer address to routes |
+| `transparent-head-requests` | `off` | HEAD handled as GET |
+| `routing.decode-max-bytes-per-chunk` | `1m` | Single `ByteString` a decoding 
directive emits |
+| `routing.decode-max-size` | `8m` | Entity size **after** decoding — see §9 |
+
+**These limits are the model's quantitative spine.** A report that a request 
*within* every documented limit causes disproportionate resource use is 
`VALID`; one that simply exceeds a limit is P1 working, and one that needs a 
limit raised is `OUT-OF-MODEL: non-default-build` (§14 Q1).
+
+### The CORS defaults — ruled (§5b, §14 Q2)
+
+`http-cors` ships:
+
+| Setting | Default |
+| --- | --- |
+| `allowed-origins` | `"*"` |
+| `allow-credentials` | `yes` |
+| `allowed-headers` | `"*"` |
+| `allowed-methods` | `["GET", "POST", "HEAD", "OPTIONS"]` |
+| `allow-generic-http-requests` | `yes` |
+
+The module's own documentation states the interaction precisely: *"if 
parameter is `*` and credentials are not allowed, a `*` is set in 
`Access-Control-Allow-Origin`. Otherwise, the origins given in the `Origin` 
request header are echoed."* *(documented — `http-cors/reference.conf`)*
+
+So with **both** defaults in force, the directive **echoes the requesting 
`Origin` and allows credentials** — the maximally permissive CORS posture. Two 
facts bound how alarming that is: the `cors()` directive is **opt-in**, so this 
affects only applications that chose to enable CORS; and it is a documented, 
deliberate default rather than an accident. It is nonetheless the most 
permissive default in the project. Its disposition follows §5b: the shipped 
value is a compatibility choice, an [...]
+
+**That ruling is about the default, never about the enforcement.** Where an 
operator has restricted `allowed-origins`, the directive must honour what they 
set, and a case where it did not was fixed at the pinned commit: 
`validateOrigins` accepted a request as soon as **one** origin in the `Origin` 
header matched, while the response echoes back **every** origin it was given, 
so a request pairing an allowed origin with a disallowed one had the disallowed 
one echoed in `Access-Control-Allow [...]
+
+---
+
+## §5b Security posture: hardening, not secure-by-default
+
+Pekko HTTP is a long-lived toolkit whose deployment base is inherited from 
Akka HTTP, and `http-cors` carries a second inheritance on top of that — its 
defaults arrived with the code donated by Lomig Mégard 
(`legal/CorsNotice.txt`). Its configuration defaults are chosen for 
compatibility with those deployments, in which operators have already been 
tasked with fronting the service (§4, §10.1) and choosing limits appropriate to 
their traffic. Changing a default to a more restrictive value  [...]
+
+Pekko HTTP therefore takes the following position *(maintainer)*:
+
+1. **Defaults are compatibility choices, not security claims.** §5a lists 
every setting whose default affects the security envelope; §10 lists what the 
operator must do as a result. Read together they are the contract: Pekko HTTP 
states what it does not provide, and states what it expects of the operator 
instead.
+2. **A report that a default should be more restrictive is not a vulnerability 
report.** It is a change request, and is closed as `BY-DESIGN: 
default-configuration` (§13). This covers the recurring ones: the CORS pair in 
§5a, `server-header` disclosing a version, and every limit someone considers 
too generous.
+3. **Proposals to change a default are welcome, and belong on the development 
list.** The PMC will weigh them in good faith on their merits — the 
compatibility cost, whether a migration path exists, and whether a major 
version is in flight. Defaults can and do change; they change through project 
discussion, not as the remediation of a security report.
+4. **If an implementation is wrong, Pekko HTTP fixes it.** Where a control 
does not do what it is documented to do once enabled, that is a defect, in 
scope, at the severity §8 assigns. **This is the sharp end of the model.** The 
§5a limits and the §8 properties are only worth what their implementations 
deliver: a `max-header-list-size` that fails to bound CONTINUATION 
accumulation, an `illegal-response-header-value-processing-mode = error` that 
lets a CRLF through, a `safeDirectoryChildP [...]
+
+**Users are free to strengthen any §5a setting**, and §10 says which ones 
matter most. What the project will not do is change the shipped value on their 
behalf.
+
+---
+
+## §6 Assumptions about inputs
+
+| Surface | Input | Attacker-controllable? | Who must enforce what |
+| --- | --- | --- | --- |
+| Any bound route | Request line (method, URI, version) | **Yes** | Pekko 
HTTP: §5a length limits |
+| Any bound route | Headers, incl. `Host`, `Cookie` | **Yes** | Pekko HTTP: 
count/length limits. App: semantic trust |
+| Any bound route | `X-Forwarded-*`, `X-Real-Ip` | **Yes** — trivially 
spoofable | **App** — surfaced by `extractClientIP`, never validated; use 
`extractDirectClientIP` for access control or rate limiting (§14 Q4) |
+| Any bound route | Entity body (fixed, chunked, streamed) | **Yes** | Pekko 
HTTP: size/chunk limits. App: content validation |
+| HTTP/2 | Frames, HPACK table, stream IDs | **Yes** | Pekko HTTP: 
`max-concurrent-streams` |
+| Route with marshaller | Entity parsed to a domain type | **Yes** | 
Underlying JSON/XML library + app |
+| `cors()` | `Origin`, `Access-Control-Request-*` | **Yes** | Operator: §5a 
CORS config |
+| File-serving directives | Path segments | **Yes** | Pekko HTTP + app — see 
§14 Q3 |
+| Client API | Response from an upstream server | **Yes** if the upstream is 
untrusted | App: treat responses as untrusted |
+| Config | `application.conf` | **No** — trusted deployment input | Operator |
+
+---
+
+## §7 Adversary model
+
+**In scope:**
+
+- **The remote HTTP client.** Can send arbitrary bytes, malformed framing, 
oversized or deeply-nested input, many concurrent connections, and abusive 
HTTP/2 frame sequences. The primary adversary — though per §14 Q1 what this 
adversary achieves through sheer *volume* is the proxy's problem, not the 
library's. *(maintainer — §14 Q7)*
+- **A malicious upstream server**, where the application uses the client API 
against an untrusted endpoint. *(maintainer — §14 Q7)*
+- **A cross-origin web attacker**, where the application enables CORS. 
*(maintainer — §14 Q2)*
+
+**Explicitly out of scope:**
+
+- **Attackers with code execution in the embedding JVM.** Already inside.
+- **The embedding application itself.** A route that deliberately leaks data 
is an application bug.
+- **Side-channel observers.** No general timing guarantees are made about 
routing or parsing. Credential comparison is the exception: 
`Credentials.Provided.verify` compares in constant time (see §8 P8), so a 
timing finding there is in scope, while one against an application-supplied 
`provideVerify` is not. *(documented — `SecurityDirectives.scala`, 
`EnhancedByteArray.scala`)*
+
+---
+
+## §8 Security properties Pekko HTTP provides
+
+| # | Property & conditions | Violation symptom | Severity | Provenance |
+| --- | --- | --- | --- | --- |
+| P1 | **Inbound messages are bounded** by the §5a limits: reaching a limit 
stops the parse rather than merely reporting it, every header a message carries 
counts towards the count limits, and buffered bytes are released from the 
accounting when the buffer is discarded | OOM or unbounded buffering from input 
*within* documented limits; a limit reached without the parse stopping | 
**Critical** | *(documented — `reference.conf`, `HttpMessageParser.scala`, 
`Http2StreamHandling.scala`)* |
+| P2 | **Response splitting is blocked**: illegal response header names and 
values are `error` by default, and the renderers drop any header whose rendered 
bytes contain CR, LF or NUL — on the HTTP/1.1 main header block, on 
chunked-response trailers and chunk extensions, and on the HTTP/2 HPACK path 
alike | CRLF or NUL in an application-supplied header, trailer or chunk 
extension reaching the wire | **Critical** | *(documented — `reference.conf`, 
`Rendering.scala:270`)* |
+| P3 | **Parse errors do not leak detail to the client** — 
`verbose-error-messages = off` | Internal parse state or stack detail in a 400 
response under defaults | High | *(documented — `reference.conf`)* |
+| P4 | **Strict URI and RFC6265 cookie parsing by default**, rather than 
lenient normalization that invites smuggling | Two components disagreeing on a 
URI or cookie under `strict` | High | *(documented — `reference.conf`)* |
+| P5 | **Connection and request lifetimes are bounded** — `idle-timeout 60s`, 
`request-timeout 20s`, `max-connections 1024`, `pipelining-limit 1` | A client 
holding resources indefinitely under defaults | High | *(documented — 
`reference.conf`)* |
+| P6 | **HTTP/2 concurrency and stream churn are bounded** — 
`max-concurrent-streams = 256` caps streams open at once, and 
`frame-type-throttle` rate-limits the frames that let a peer cycle through that 
cap: `RST_STREAM` is charged by default at 100 per second with a burst of 100. 
Concurrency alone is not a bound on *work*, because a reset frees the slot 
immediately — this is the HTTP/2 Rapid Reset shape (CVE-2023-44487) | Unbounded 
stream/state growth on one connection, or unbounded str [...]
+| P7 | **HTTP/2 header blocks are bounded** — `max-header-list-size = 64 KiB` 
caps the decompressed header list *and* the accumulated HEADERS + CONTINUATION 
fragments, so a header block the peer never terminates with `END_HEADERS` 
cannot grow without bound; over-limit blocks get `GOAWAY(ENHANCE_YOUR_CALM)` 
rather than being buffered | Unbounded buffering from a CONTINUATION flood or 
an oversized header list | **Critical** | *(documented — `reference.conf`)* |
+| P8 | **Credential comparison is constant-time** where the verifier calls 
`Credentials.verify` — it compares via `secure_==`, which XOR-accumulates over 
the full length after a length check, rather than short-circuiting on the first 
differing byte | Secret recoverable byte-by-byte from response timing against a 
`verify`-based verifier | High | *(documented — `SecurityDirectives.scala`, 
`EnhancedByteArray.scala:37`)* |
+
+**P1-P7 are default-on properties** — a notable contrast with `apache/pekko`, 
where the strongest controls must be switched on. P8 is the exception: it holds 
only for a verifier that calls `Credentials.verify`, which is why §10.4 states 
it as a downstream responsibility. The boundary of the DoS claim, once this 
model's largest ambiguity, is now fixed by the §14 Q1 content-vs-volume line.
+
+**A note on how P1 came to be stated this precisely.** P1 has the same history 
as P2, and for the same reason: the draft asserted it from the §5a table, which 
records what each limit is *supposed* to bound. Three of those bounds did not 
hold as written, all fixed at the pinned commit. `max-chunk-count` was tested 
without an `else` branch, so the `StateResult` of `failEntityStream` was 
discarded and the parser trampolined into the next chunk — reaching the limit 
emitted an error per remai [...]
+
+**One bound is missing at the pinned commit, and P1 is stated with that gap 
open.** The HTTP/2 frame parser reads a frame's 24-bit length field and then 
takes that many bytes with no upper limit (`Http2FrameParsing.scala:193-200`), 
so a peer can make it buffer up to 16 MiB - 1 for a single frame. That happens 
*before* HPACK decoding and before the entity is assembled, so none of the 
three HTTP/2 buffer bounds in §5a constrain it, and the cost is multiplied by 
the number of connections. A [...]
+
+**A note on how P2 came to be stated this precisely.** The draft asserted P2 
from the two `reference.conf` processing-mode defaults alone, without walking 
the path those settings are supposed to govern. Walking it found the guard was 
not where the claim assumed: it lived in one `~~(HttpHeader)` overload, so 
chunked-response **trailers** and **chunk extensions** were rendered around it 
([#1256](https://github.com/apache/pekko-http/pull/1256)), it tested for CR and 
LF but not **NUL** ([#12 [...]
+
+---
+
+## §9 Security properties Pekko HTTP does **not** provide
+
+- **No claim of complete DoS resistance.** The documented wording is *"behaves 
pretty well under most known Denial of Service attacks"*, immediately followed 
by a recommendation to front it with a load balancer or enterprise routing 
solution *(documented — `security.md`)*. Per §14 Q1 this disclaimer is **scoped 
to volume**: Pekko HTTP does not claim to withstand floods, but it *does* claim 
that one in-limits request cannot provoke disproportionate work — that part is 
P1, and a violation  [...]
+- **No edge hardening.** Rate limiting, IP reputation, request scrubbing, 
connection-count throttling beyond `max-connections`, slow-loris mitigation 
beyond `idle-timeout` — none are provided, and none are planned. *(maintainer — 
§14 Q1)*
+- **No authentication or authorization.** The security directives are 
plumbing; the credential check is the application's function. *(maintainer — 
§14 Q7)*
+- **No CSRF protection.** No token issuance or verification is provided. 
*(maintainer — §14 Q7)*
+- **No output encoding / XSS defence.** Pekko HTTP renders what the 
application marshals. *(maintainer — §14 Q7)*
+- **No trusted client-IP derivation from headers.** `extractClientIP` surfaces 
`X-Forwarded-For` / `X-Real-Ip` without validating them, and Pekko HTTP has no 
trusted-proxy chain configuration. `extractDirectClientIP` is the trustworthy 
accessor, but it yields the last proxy rather than the client. See §5 and §14 
Q4.
+
+### False friends
+
+- **The security directives are not a security *system*.** `authenticateBasic` 
and `authenticateOAuth2` route credentials to an application-supplied verifier; 
they impose no password policy, no rate limiting and no lockout. They *do* 
supply a constant-time comparison (§8 P8) — but only to a verifier that calls 
`Credentials.verify`; one that pattern-matches the secret out and uses `==` 
gets none of it.
+- **`allowed-origins = "*"` does not mean "no credentials are exposed".** 
Combined with the shipped `allow-credentials = yes`, it echoes the caller's 
`Origin` (§5a).
+- **`remote-address-attribute` is not the client IP behind a proxy.** It is 
the socket peer.
+- **`max-content-length` is not a global memory bound.** It bounds one entity; 
concurrent connections multiply it.
+- **A rejection is not a failure.** The routing DSL's rejection mechanism is 
control flow, not a security control — an unhandled rejection can fall through 
to a different route.
+
+### Well-known attack classes left to the caller
+
+- **Request smuggling / desync** between a fronting proxy and Pekko HTTP — 
inherently a two-party property; strict parsing (P4) helps but cannot settle it 
alone. What Pekko HTTP does own is its own framing decision, and a case where 
it framed a message by a different rule than a conformant upstream would is a 
defect here rather than a two-party stalemate: a `Transfer-Encoding` whose 
value failed to parse was degraded to a `RawHeader`, never reached the modelled 
`Transfer-Encoding` arm of [...]
+- **Slow-loris and connection exhaustion** — `idle-timeout` and 
`max-connections` (P5) bound what one connection holds and how many are 
accepted, but exhausting those bounds by volume is disclaimed (§14 Q1). A 
single connection that evades `idle-timeout` while holding resources is the 
in-scope version.
+- **Decompression bombs** are *not* wholly left to the caller. Where the 
application decodes through the routing DSL, `decodeRequest` / 
`decodeRequestWith` bound the result on both axes: the decoder's per-chunk 
output is set to `decode-max-bytes-per-chunk` (`1m`) and the decoded stream is 
wrapped in `withSizeLimit(decode-max-size)` (`8m`), so a small gzip body that 
expands past the limit fails the stream instead of filling the heap 
(`CodingDirectives.scala:93-102`). Every `decodeRequest* [...]
+- **SSRF** via the client API, where the application takes a URL from a 
request.
+- **Path traversal** is left to the caller in some of the file-serving 
directives and not others, and the split is worth stating precisely (§14 Q3). 
`getFromDirectory`, `listDirectoryContents` and the 
`getFromBrowseableDirector*` pair built on them run the unmatched path through 
`safeDirectoryChildPath`, which applies both a segment filter and canonical 
containment against the served root — containment is claimed there, so a 
genuine escape is `VALID` per §5b.4. `getFromResourceDirectory` [...]
+- **XXE** in XML marshallers — a property of the underlying parser.
+
+---
+
+## §10 Downstream responsibilities
+
+1. **Put an enterprise-grade proxy or load balancer in front** of an 
internet-facing service *(documented — `security.md`)*.
+2. **Do not raise the §5a limits without understanding the memory cost** — 
each is multiplied by concurrent connections.
+3. **If CORS is enabled, set `allowed-origins` explicitly.** Do not ship the 
`"*"` + `allow-credentials = yes` combination to a credentialed API (§5a).
+4. **Compare credentials with `Credentials.verify`**, which is constant-time 
(§8 P8) — not with `==` on the secret, and not via `provideVerify` unless the 
supplied verifier is itself constant-time.
+5. **Use `extractDirectClientIP`, not `extractClientIP`, for access control, 
rate limiting or audit logging.** The latter reads `X-Forwarded-For` / 
`X-Real-Ip`, which the client controls unless a trusted proxy overwrites them; 
it requires `remote-address-attribute = on` to fall back usefully. Derive 
identity from `X-Forwarded-For` only where a trusted proxy sets it and you 
validate the chain yourself.
+6. **Validate and canonicalize any request-derived path** before passing it to 
a file-serving directive.
+7. **Treat client-API responses from untrusted upstreams as untrusted input.**
+8. **Consider `server-header = ""`** if product/version disclosure matters to 
your threat model.
+
+---
+
+## §11 Known misuse patterns
+
+- **Exposing a Pekko HTTP service directly to the internet** with no fronting 
proxy, contrary to the documented recommendation.
+- **Enabling `cors()` and leaving `allowed-origins = "*"`** on an API that 
uses cookies or bearer tokens.
+- **Reaching for `extractClientIP`** — the more discoverable name — for rate 
limiting, audit logging or access control, where `extractDirectClientIP` is the 
one that cannot be chosen by the caller.
+- **Raising `max-content-length` to `infinite`** to accept large uploads, 
without a concurrency bound.
+- **Comparing credentials with `==`** inside an `authenticateBasic` verifier — 
or reaching for `provideVerify` with a non-constant-time verifier — instead of 
`Credentials.verify`.
+- **Passing a request path segment straight to `getFromFile` or 
`getFromResource`.** Neither filters what it is handed. `getFromResource` is 
the easier of the two to get wrong: it looks like the resource-side sibling of 
`getFromResourceDirectory`, but where that directive routes the request path 
through `safeJoinPaths` before delegating, `getFromResource` passes the name to 
`classLoader.getResource` with only a trailing-slash check to keep directory 
resources unserved (`FileAndResourceDi [...]
+- **Turning `verbose-error-messages = on`** in production to aid debugging.
+
+---
+
+## §11a Known non-findings (recurring false positives)
+
+- **"`Server` header discloses the product and version."** Documented default, 
configurable via `server-header` (§5a). Not a vulnerability under this model; a 
request to blank it by default is `BY-DESIGN: default-configuration` per §5b.
+- **"No authentication on routes."** Authentication is the application's 
responsibility (§9). A scan of this library cannot conclude a route is 
unauthenticated.
+- **"Request exceeding `max-uri-length` / `max-header-count` is rejected."** 
That is P1 working.
+- **"N concurrent connections / requests exhaust CPU, memory or sockets."** 
Volume-based resource exhaustion is `BY-DESIGN: property-disclaimed` per §14 Q1 
— defence belongs to the fronting proxy (§10.1). Reports must show *one* 
in-limits request doing disproportionate work, not many requests doing 
proportionate work. A load-generator result is not a finding.
+- **"`extractClientIP` trusts a client-supplied header."** By design and 
documented at the directive, with `extractDirectClientIP` provided as the 
trustworthy alternative (§14 Q4). `BY-DESIGN: property-disclaimed`. A report 
that `extractDirectClientIP` can be influenced by a header *is* in scope.
+- **"CORS allows any origin."** Reflects the shipped default and requires the 
application to have opted into `cors()`. A request to change the default is 
`BY-DESIGN: default-configuration` per §5b; a misconfigured deployment is a 
finding against the *application*, not the library.
+- **"`allow-credentials = yes` with `allowed-origins = "*"` sends 
`Access-Control-Allow-Origin: *` with credentials."** It does not — the literal 
`*` is sent only when `allowCredentials` is false, otherwise the request 
`Origin` is echoed (`CorsSettingsImpl.scala:63`, covered by 
`CorsDirectivesSpec`). Reports asserting the literal `*`-with-credentials 
combination are factually wrong.
+- **"Credential comparison is vulnerable to a timing attack."** Check which 
comparator the report exercises: `Credentials.verify` is constant-time (§8 P8), 
so the claim is wrong against it; against an application's own `provideVerify` 
comparator it is a finding in that application, not this library.
+- **Findings in `*-tests`, `http-testkit*`, `http-bench-jmh`, `http-scalafix`, 
`docs`** — `OUT-OF-MODEL: unsupported-component` per §3.
+- **"The process registers JVM shutdown hooks."** Pekko HTTP registers none 
(§5, §14 Q9). The hooks are `CoordinatedShutdown`'s and, with remoting enabled, 
Artery's — they belong to `apache/pekko`'s model. `OUT-OF-MODEL: 
unsupported-component`.
+- **Findings in the actor or stream layer** — belongs to `apache/pekko`'s 
model, not this one.
+
+---
+
+## §12 Conditions that would change this model
+
+- A change to any §5a **default**, especially a parsing limit, a timeout, or a 
CORS setting.
+- A new protocol version or transport (HTTP/3).
+- Taking on any authentication, authorization, or rate-limiting responsibility 
currently disclaimed in §9.
+- A change to the documented "do not expose directly" posture in `security.md`.
+- Promotion of a §3 module into the supported surface.
+- A change to the §5 process-behaviour claims. One near-miss is on record: 
[#1217](https://github.com/apache/pekko-http/pull/1217) originally replaced the 
per-upload `deleteOnExit` with a raw JVM shutdown hook registered by Pekko HTTP 
itself, which would have invalidated the "registers no shutdown hook" claim in 
§5 and the matching §11a non-finding; it was reworked in review to register the 
cleanup as a `CoordinatedShutdown` task on the actor system instead, and merged 
in that form, so t [...]
+- **A report that cannot be routed to exactly one §13 disposition** — evidence 
of a model gap; revise the model rather than making an ad-hoc call.
+
+---
+
+## §13 Triage dispositions
+
+| Disposition | Meaning | Licensed by |
+| --- | --- | --- |
+| `VALID` | Violates a §8 property via an in-scope adversary and input. For 
resource exhaustion: a **single request within all §5a limits** causing 
super-linear CPU or memory | §6, §7, §8, §14 Q1 |
+| `VALID-HARDENING` | No §8 property violated, but the API makes a §11 misuse 
easy enough to warrant hardening. Typically no CVE | §11 |
+| `OUT-OF-MODEL: trusted-input` | Requires control of an input §6 marks 
trusted (configuration, application-supplied handlers) | §6 |
+| `OUT-OF-MODEL: adversary-not-in-scope` | Requires in-JVM code execution, or 
a malicious embedding application | §7 |
+| `OUT-OF-MODEL: unsupported-component` | Lands in a §3 module, or in the 
actor/stream layer | §3 |
+| `OUT-OF-MODEL: non-default-build` | Only manifests under a non-default §5a 
setting — including any resource-exhaustion report that needs a limit 
**raised** from its default. Distinct from `default-configuration`: this is a 
real defect reachable only off-default, that one is no defect at all | §5a, §14 
Q1 |
+| `BY-DESIGN: default-configuration` | Asks that a §5a default be changed to a 
more restrictive value. Not a vulnerability; §5b.3 invites the proposal on the 
development list | §5b |
+| `BY-DESIGN: property-disclaimed` | Concerns a §9 property — authentication, 
CSRF, XSS, edge hardening — or depends on request **volume** rather than 
request **content** | §9, §14 Q1 |
+| `KNOWN-NON-FINDING` | Matches a §11a pattern | §11a |
+| `MODEL-GAP` | Routable to none of the above — triggers §12 | §12 |
+
+---
+
+## §14 Open questions for the maintainers
+
+Each states a **proposed answer**; confirming or correcting is enough.
+
+**Q1 — Where exactly is the DoS line? — ANSWERED.** *(maintainer)*
+The proposed split was accepted as written. The **DoS line** is now settled 
model, restated here as the canonical form and applied throughout §4, §5a, §8, 
§9, §11a and §13:
+
+> A **single request within every §5a documented limit** that provokes 
super-linear CPU or memory is `VALID` — this is the P1 violation symptom.
+> A finding that requires a §5a limit to be **raised** from its shipped 
default is `OUT-OF-MODEL: non-default-build`.
+> A finding that depends on request **volume** rather than request **content** 
— connection floods, slow-loris at scale, aggregate bandwidth — is `BY-DESIGN: 
property-disclaimed`. Volume defence is the fronting proxy's job (§10.1).
+
+The operative test is *content vs. volume*: one well-formed, in-limits request 
doing disproportionate work is a bug in Pekko HTTP; many requests doing 
proportionate work is a deployment concern.
+
+**Q2 — The CORS defaults. ANSWERED *(maintainer)*.** **Answer:** a 
compatibility default under §5b. The values arrived with the donated 
`http-cors` code and existing users depend on them; `cors()` is opt-in, and an 
application that enables it is expected to configure it, with §10.3 stating 
what to set. A report that the shipped default should change is `BY-DESIGN: 
default-configuration` — welcome on the development list, not as a security 
report. What *is* in scope is the implementation: [...]
+
+**Q3 — File-serving directives. ANSWERED *(maintainer)*.** *Resolved from code 
— and, like Q4 and Q5, a correction: the draft asserted containment held, and 
reviewing the check found a defect in it.* `safeDirectoryChildPath` claims 
containment by two measures: a path segment must not be `..` and must not 
contain `/` or `\\`; and the resolved file's `File.getCanonicalPath` must be 
prefixed by the base path's. The second measure compared the canonical paths as 
**strings** (`canonicalFinalP [...]
+
+**Q4 — `X-Forwarded-For` and client identity. ANSWERED *(maintainer)*.** The 
disposition is confirmed, but the draft's stated basis for it was wrong and is 
corrected here. Pekko HTTP **does** parse forwarding headers: `extractClientIP` 
resolves `X-Forwarded-For` (first address) → `X-Real-Ip` → the `remoteAddress` 
attribute, in that order (`MiscDirectives.scala:142-145`). What is true is that 
it never does so *implicitly* — `remote-address-attribute` populates the 
attribute from the socke [...]
+
+**Answer:** the spoofability is documented at the directive rather than 
defended against. `extractClientIP`'s own scaladoc warns that *"the headers are 
under the control of the client unless a trusted proxy in front of this server 
overwrites them"* and directs the reader to `extractDirectClientIP` *"where the 
address must not be chosen by the client, for example for access control or 
rate limiting"* — a directive added for exactly this purpose (#1219, `@since 
2.0.0`), which reads the att [...]
+
+**Q5 — Constant-time credential comparison. ANSWERED *(maintainer)*.** 
*Resolved from code — this document's earlier draft had it backwards.* 
`Credentials.Provided.verify` does compare, via `secure_==` 
(`EnhancedByteArray.scala:37`), which is constant-time; the library therefore 
**does** provide the guarantee, recorded as §8 P8. It is conditional on the 
verifier calling `verify` — `provideVerify` hands the raw secret to application 
code and waives it. **Answer *(maintainer)*:** the split [...]
+
+**Q6 — Module in/out split (§2 table). ANSWERED *(maintainer)*.** **Answer:** 
the split shown in §2 is confirmed as the maintainers' own, not merely the ASF 
Security team's proposal. `http-caching` is **in** model — cache-key confusion 
is a real class and the directive ships as part of the supported surface. 
`http-scalafix` is correctly **out**, along with the test kits, 
`http-bench-jmh`, `docs`, `project`, `scripts` and `legal`: a finding in any of 
them is `OUT-OF-MODEL: unsupported-com [...]
+
+**Q7 — The §3/§7/§9 non-goals. ANSWERED *(maintainer)*.** **Answer:** the 
split is confirmed as stated. Pekko HTTP provides **no** authentication system, 
authorization policy, CSRF protection or XSS/output encoding — reports against 
those are `BY-DESIGN: property-disclaimed` per §9. **Out** of the adversary 
model: attackers with code execution in the embedding JVM, and a malicious 
embedding application (a route that deliberately leaks is an application bug). 
**In**: the remote HTTP clien [...]
+
+**Q8 — TLS. ANSWERED *(maintainer)*.** **Answer:** confirmed. Where Pekko HTTP 
terminates TLS via `HttpsConnectionContext`, protocol and cipher selection come 
from the JSSE context the application supplies; Pekko HTTP neither pins a 
cipher suite nor overrides the JDK's defaults. "Weak cipher accepted" is 
therefore a deployment finding against that context or the JDK, not a library 
one — `OUT-OF-MODEL: trusted-input` per §6, which marks configuration as 
operator-supplied. A defect in how  [...]
+
+On the second half: **in-process termination is supported**, and 
`HttpsConnectionContext` is a first-class API. It is not, however, the posture 
the documentation steers production deployments toward — §4's quoted 
recommendation to front the service with an enterprise-grade routing solution 
or load balancer applies to TLS as much as to volume defence (§14 Q1), and in 
such a deployment termination is commonly the proxy's job. Both are supported; 
the fronted one is what the docs recommend.
+
+**Q9 — The negative claims in §5. ANSWERED *(maintainer)*, with one 
correction.** *Resolved from code, then ruled on.* Scanned the main sources of 
`http-core`, `http`, `parsing`, `http-caching` and `http-cors`: no 
`addShutdownHook`, no `ProcessBuilder`/`Runtime.exec`, no 
`Signal`/`SignalHandler`, no `System.setProperty`/`Security.*`/`setDefault`, 
and no bind outside the public `Http().bind*` entry points. **The file-writing 
claim did not survive review:** the scan missed `FileUploadDirec [...]
+
+**Answer:** state the boundary here rather than deferring it. The 
`ActorSystem`'s shutdown hooks are worth **highlighting** in §5 so an 
integrator is not surprised by them, but the claim this document makes and 
stands behind is that **Pekko HTTP registers none of its own**. A report that 
Pekko HTTP installs a shutdown hook is factually wrong (§11a); one about the 
hooks `CoordinatedShutdown` or Artery register belongs to `apache/pekko`'s 
model, and is `OUT-OF-MODEL: unsupported-component` here.
+
+**Q10 — Coexistence. ANSWERED *(maintainer)*.** Following the split adopted in 
[`apache/pekko#3478`](https://github.com/apache/pekko/pull/3478). Three 
documents carry security information, each canonical for one thing:
+
+| Document | Canonical for | Reached by |
+| --- | --- | --- |
+| [`SECURITY.md`](SECURITY.md) | **The reporting policy.** The strongest and 
canonical statement of how to report and what the project undertakes | Anyone 
arriving via the repository, and every other document |
+| `THREAT_MODEL.md` (this document) | **Scope** — what is and is not a 
vulnerability, and how a report is triaged | Reporters, triagers, scanning 
tools |
+| `docs/src/main/paradox/security.md` | Security announcements, and the 
documentation-site index of security material | Readers of the documentation 
site |
+
+Every other document **links** to `SECURITY.md` for the reporting policy and 
to this document for scope, rather than restating either. A change to the 
policy is therefore made in one place.
+
+**Note the correction to the draft's proposal.** It suggested that 
`security.md`'s "Security model" section be reduced to a pointer here. It is 
*not*, and must not be: §4 quotes that section verbatim as the documented 
source of the "should not be exposed to the public internet directly" posture, 
and §15 back-maps four separate claims to it. Reducing it to a pointer would 
delete the evidence this document is built on and leave §4 citing a redirect. 
The section stays; `security.md` gains l [...]
+
+**One statement is referred, not migrated.** `security.md` carries an 
upstream-coordination sentence that `SECURITY.md` does not: *"Ideally, any 
issues affecting Apache Pekko and Akka should be reported to Apache team first. 
We will share the report with the Lightbend Akka team."* Per the same ruling, a 
reporting statement living outside `SECURITY.md` is referred to the maintainers 
for a decision — promoted verbatim or dropped, never silently moved. It is left 
untouched in `security.md`  [...]
+
+---
+
+## §15 Appendix — back-map from existing docs
+
+| Existing statement | Source | Lands in |
+| --- | --- | --- |
+| Applications should not be exposed to the public internet directly | 
`security.md` | §3, §4, §10.1 |
+| Behaves "pretty well" under most known DoS attacks — scoped to *volume* by 
the §14 Q1 ruling | `security.md` + maintainer ruling | §4, §9, §11a, §13, §14 
Q1 |
+| An enterprise-grade routing solution or LB (httpd, Nginx) is safer | 
`security.md` | §5, §10.1 |
+| Report privately per ASF guidelines; subscribe to announce@ | `security.md` 
| `SECURITY.md`, §1 |
+| Parsing limits (`max-uri-length`, `max-header-*`, `max-chunk-*`, …) | 
`http-core/reference.conf` | §5a, §8 P1 |
+| `verbose-error-messages = off` | `http-core/reference.conf` | §5a, §8 P3 |
+| Illegal response header name/value processing = `error` | 
`http-core/reference.conf` | §5a, §8 P2 |
+| `uri-parsing-mode = strict`, `cookie-parsing-mode = rfc6265` | 
`http-core/reference.conf` | §5a, §8 P4 |
+| Timeouts and connection caps | `http-core/reference.conf` | §5a, §8 P5 |
+| `max-concurrent-streams = 256` | `http-core/reference.conf` | §5a, §8 P6 |
+| `max-header-list-size = 64 KiB`, bounding HEADERS + CONTINUATION 
accumulation | `http-core/reference.conf` | §5a, §8 P7 |
+| `frame-type-throttle` charging `RST_STREAM` by default, against HTTP/2 Rapid 
Reset (CVE-2023-44487) | `http-core/reference.conf` | §5a, §8 P6 |
+| HTTP/2 incoming buffer bounds (`incoming-connection-level-buffer-size = 10 
MB`, `incoming-stream-level-buffer-size = 512kB`) and 
`outgoing-control-frame-buffer-size = 1024` | `http-core/reference.conf` | §5a, 
§8 P1 |
+| Decoding limits (`decode-max-bytes-per-chunk = 1m`, `decode-max-size = 8m`), 
applied by the `decodeRequest*` directives | `http/reference.conf`, 
`CodingDirectives.scala` | §5a, §9 |
+| `Credentials.verify` compares via constant-time `secure_==` | 
`SecurityDirectives.scala`, `EnhancedByteArray.scala` | §7, §8 P8, §9, §10.4, 
§14 Q5 |
+| `safeDirectoryChildPath` rejects `..`/separator segments and enforces 
canonical containment (its string-prefix comparison was found defective in 
review; fixed by [#1218](https://github.com/apache/pekko-http/pull/1218)) | 
`FileAndResourceDirectives.scala` | §9, §14 Q3 |
+| `remote-address-attribute = off` | `http-core/reference.conf` | §5, §9, §14 
Q4 |
+| `extractClientIP` reads `X-Forwarded-For`/`X-Real-Ip`; 
`extractDirectClientIP` reads the attribute alone | `MiscDirectives.scala` | 
§5, §6, §9, §10.5, §11a, §14 Q4 |
+| CORS: `*` + credentials echoes the request `Origin` | 
`http-cors/reference.conf` | §5a, §9, §11a, §14 Q2 |
+| `http-cors` code donated by Lomig Mégard, defaults inherited with it | 
`legal/CorsNotice.txt`, `NOTICE` | §5b, §14 Q2 |
diff --git a/docs/src/main/paradox/security.md 
b/docs/src/main/paradox/security.md
index 364c0a977..043e121f5 100644
--- a/docs/src/main/paradox/security.md
+++ b/docs/src/main/paradox/security.md
@@ -15,7 +15,9 @@ This mailing list also has announcements of releases for 
Apache projects.
 
 ## Reporting Vulnerabilities
 
-We strongly encourage people to report such problems to our private security 
mailing list first, before disclosing them in a public forum.
+We strongly encourage people to report such problems privately to the Apache 
Security team at
+`[email protected]` first, before disclosing them in a public forum. Apache 
Pekko does not
+operate a separate project security list.
 
 Please follow the [guidelines](https://www.apache.org/security/) laid down by 
the Apache Security team.
 
@@ -25,3 +27,5 @@ report with the Lightbend Akka team.
 ## References
 
  * [Akka HTTP security 
fixes](https://doc.akka.io/docs/akka-http/10.2/security.html)
+ * [Security 
Policy](https://github.com/apache/pekko-http/blob/main/SECURITY.md)
+ * [Threat 
Model](https://github.com/apache/pekko-http/blob/main/THREAT_MODEL.md)


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to